From d3055c097d02dbf28ba5a6434f5577f99be3fe69 Mon Sep 17 00:00:00 2001 From: zaharovadasha Date: Thu, 1 Mar 2018 17:25:04 +0300 Subject: [PATCH 1/7] lab1 project structure --- gtest/gtest-all.cc | 9592 +++++++++++ gtest/gtest.h | 20063 ++++++++++++++++++++++ include/monom.h | 1 + include/polinom.h | 6 + samples/main_polinom.cpp | 5 + sln/vc9/gtest/gtest.vcproj | 169 + sln/vc9/gtest/gtest.vcxproj | 84 + sln/vc9/gtest/gtest.vcxproj.filters | 23 + sln/vc9/polinom/polinom.vcproj | 179 + sln/vc9/polinom/polinom.vcxproj | 88 + sln/vc9/polinom/polinom.vcxproj.filters | 29 + sln/vc9/polinoms.sln | 40 + sln/vc9/sample/sample.vcproj | 187 + sln/vc9/sample/sample.vcxproj | 107 + sln/vc9/sample/sample.vcxproj.filters | 14 + sln/vc9/tests/tests.vcproj | 195 + sln/vc9/tests/tests.vcxproj | 113 + sln/vc9/tests/tests.vcxproj.filters | 17 + src/monom.cpp | 1 + src/polinom.cpp | 1 + test/test_main.cpp | 6 + test/test_polinom.cpp | 4 + 22 files changed, 30924 insertions(+) create mode 100644 gtest/gtest-all.cc create mode 100644 gtest/gtest.h create mode 100644 include/monom.h create mode 100644 include/polinom.h create mode 100644 samples/main_polinom.cpp create mode 100644 sln/vc9/gtest/gtest.vcproj create mode 100644 sln/vc9/gtest/gtest.vcxproj create mode 100644 sln/vc9/gtest/gtest.vcxproj.filters create mode 100644 sln/vc9/polinom/polinom.vcproj create mode 100644 sln/vc9/polinom/polinom.vcxproj create mode 100644 sln/vc9/polinom/polinom.vcxproj.filters create mode 100644 sln/vc9/polinoms.sln create mode 100644 sln/vc9/sample/sample.vcproj create mode 100644 sln/vc9/sample/sample.vcxproj create mode 100644 sln/vc9/sample/sample.vcxproj.filters create mode 100644 sln/vc9/tests/tests.vcproj create mode 100644 sln/vc9/tests/tests.vcxproj create mode 100644 sln/vc9/tests/tests.vcxproj.filters create mode 100644 src/monom.cpp create mode 100644 src/polinom.cpp create mode 100644 test/test_main.cpp create mode 100644 test/test_polinom.cpp diff --git a/gtest/gtest-all.cc b/gtest/gtest-all.cc new file mode 100644 index 000000000..ff9e51235 --- /dev/null +++ b/gtest/gtest-all.cc @@ -0,0 +1,9592 @@ +// Copyright 2008, 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: mheule@google.com (Markus Heule) +// +// Google C++ Testing Framework (Google Test) +// +// Sometimes it's desirable to build Google Test by compiling a single file. +// This file serves this purpose. + +// This line ensures that gtest.h can be compiled on its own, even +// when it's fused. +#include "gtest.h" + +// The following lines pull in the real gtest *.cc files. +// 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 +// 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) +// +// The Google C++ Testing Framework (Google Test) + +// 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) +// +// Utilities for testing Google Test itself and code that uses Google Test +// (e.g. frameworks built on top of Google Test). + +#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_ +#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_ + + +namespace testing { + +// This helper class can be used to mock out Google Test failure reporting +// so that we can test Google Test or code that builds on Google Test. +// +// An object of this class appends a TestPartResult object to the +// TestPartResultArray object given in the constructor whenever a Google Test +// failure is reported. It can either intercept only failures that are +// generated in the same thread that created this object or it can intercept +// all generated failures. The scope of this mock object can be controlled with +// the second argument to the two arguments constructor. +class GTEST_API_ ScopedFakeTestPartResultReporter + : public TestPartResultReporterInterface { + public: + // The two possible mocking modes of this object. + enum InterceptMode { + INTERCEPT_ONLY_CURRENT_THREAD, // Intercepts only thread local failures. + INTERCEPT_ALL_THREADS // Intercepts all failures. + }; + + // The c'tor sets this object as the test part result reporter used + // by Google Test. The 'result' parameter specifies where to report the + // results. This reporter will only catch failures generated in the current + // thread. DEPRECATED + explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result); + + // Same as above, but you can choose the interception scope of this object. + ScopedFakeTestPartResultReporter(InterceptMode intercept_mode, + TestPartResultArray* result); + + // The d'tor restores the previous test part result reporter. + virtual ~ScopedFakeTestPartResultReporter(); + + // Appends the TestPartResult object to the TestPartResultArray + // received in the constructor. + // + // This method is from the TestPartResultReporterInterface + // interface. + virtual void ReportTestPartResult(const TestPartResult& result); + private: + void Init(); + + const InterceptMode intercept_mode_; + TestPartResultReporterInterface* old_reporter_; + TestPartResultArray* const result_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter); +}; + +namespace internal { + +// A helper class for implementing EXPECT_FATAL_FAILURE() and +// EXPECT_NONFATAL_FAILURE(). Its destructor verifies that the given +// TestPartResultArray contains exactly one failure that has the given +// type and contains the given substring. If that's not the case, a +// non-fatal failure will be generated. +class GTEST_API_ SingleFailureChecker { + public: + // The constructor remembers the arguments. + SingleFailureChecker(const TestPartResultArray* results, + TestPartResult::Type type, + const string& substr); + ~SingleFailureChecker(); + private: + const TestPartResultArray* const results_; + const TestPartResult::Type type_; + const string substr_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker); +}; + +} // namespace internal + +} // namespace testing + +// A set of macros for testing Google Test assertions or code that's expected +// to generate Google Test fatal failures. It verifies that the given +// statement will cause exactly one fatal Google Test failure with 'substr' +// being part of the failure message. +// +// There are two different versions of this macro. EXPECT_FATAL_FAILURE only +// affects and considers failures generated in the current thread and +// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. +// +// The verification of the assertion is done correctly even when the statement +// throws an exception or aborts the current function. +// +// Known restrictions: +// - 'statement' cannot reference local non-static variables or +// non-static members of the current object. +// - 'statement' cannot return a value. +// - You cannot stream a failure message to this macro. +// +// Note that even though the implementations of the following two +// macros are much alike, we cannot refactor them to use a common +// helper macro, due to some peculiarity in how the preprocessor +// works. The AcceptsMacroThatExpandsToUnprotectedComma test in +// gtest_unittest.cc will fail to compile if we do that. +#define EXPECT_FATAL_FAILURE(statement, substr) \ + do { \ + class GTestExpectFatalFailureHelper {\ + public:\ + static void Execute() { statement; }\ + };\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter:: \ + INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ + GTestExpectFatalFailureHelper::Execute();\ + }\ + } while (::testing::internal::AlwaysFalse()) + +#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ + do { \ + class GTestExpectFatalFailureHelper {\ + public:\ + static void Execute() { statement; }\ + };\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter:: \ + INTERCEPT_ALL_THREADS, >est_failures);\ + GTestExpectFatalFailureHelper::Execute();\ + }\ + } while (::testing::internal::AlwaysFalse()) + +// A macro for testing Google Test assertions or code that's expected to +// generate Google Test non-fatal failures. It asserts that the given +// statement will cause exactly one non-fatal Google Test failure with 'substr' +// being part of the failure message. +// +// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only +// affects and considers failures generated in the current thread and +// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. +// +// 'statement' is allowed to reference local variables and members of +// the current object. +// +// The verification of the assertion is done correctly even when the statement +// throws an exception or aborts the current function. +// +// Known restrictions: +// - You cannot stream a failure message to this macro. +// +// Note that even though the implementations of the following two +// macros are much alike, we cannot refactor them to use a common +// helper macro, due to some peculiarity in how the preprocessor +// works. If we do that, the code won't compile when the user gives +// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that +// expands to code containing an unprotected comma. The +// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc +// catches that. +// +// For the same reason, we have to write +// if (::testing::internal::AlwaysTrue()) { statement; } +// instead of +// GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) +// to avoid an MSVC warning on unreachable code. +#define EXPECT_NONFATAL_FAILURE(statement, substr) \ + do {\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ + (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter:: \ + INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ + if (::testing::internal::AlwaysTrue()) { statement; }\ + }\ + } while (::testing::internal::AlwaysFalse()) + +#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ + do {\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ + (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \ + >est_failures);\ + if (::testing::internal::AlwaysTrue()) { statement; }\ + }\ + } while (::testing::internal::AlwaysFalse()) + +#endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include // NOLINT +#include +#include + +#if GTEST_OS_LINUX + +// TODO(kenton@google.com): Use autoconf to detect availability of +// gettimeofday(). +# define GTEST_HAS_GETTIMEOFDAY_ 1 + +# include // NOLINT +# include // NOLINT +# include // NOLINT +// Declares vsnprintf(). This header is not available on Windows. +# include // NOLINT +# include // NOLINT +# include // NOLINT +# include // NOLINT +# include + +#elif GTEST_OS_SYMBIAN +# define GTEST_HAS_GETTIMEOFDAY_ 1 +# include // NOLINT + +#elif GTEST_OS_ZOS +# define GTEST_HAS_GETTIMEOFDAY_ 1 +# include // NOLINT + +// On z/OS we additionally need strings.h for strcasecmp. +# include // NOLINT + +#elif GTEST_OS_WINDOWS_MOBILE // We are on Windows CE. + +# include // NOLINT + +#elif GTEST_OS_WINDOWS // We are on Windows proper. + +# include // NOLINT +# include // NOLINT +# include // NOLINT +# include // NOLINT + +# if GTEST_OS_WINDOWS_MINGW +// MinGW has gettimeofday() but not _ftime64(). +// TODO(kenton@google.com): Use autoconf to detect availability of +// gettimeofday(). +// TODO(kenton@google.com): There are other ways to get the time on +// Windows, like GetTickCount() or GetSystemTimeAsFileTime(). MinGW +// supports these. consider using them instead. +# define GTEST_HAS_GETTIMEOFDAY_ 1 +# include // NOLINT +# endif // GTEST_OS_WINDOWS_MINGW + +// cpplint thinks that the header is already included, so we want to +// silence it. +# include // NOLINT + +#else + +// Assume other platforms have gettimeofday(). +// TODO(kenton@google.com): Use autoconf to detect availability of +// gettimeofday(). +# define GTEST_HAS_GETTIMEOFDAY_ 1 + +// cpplint thinks that the header is already included, so we want to +// silence it. +# include // NOLINT +# include // NOLINT + +#endif // GTEST_OS_LINUX + +#if GTEST_HAS_EXCEPTIONS +# include +#endif + +#if GTEST_CAN_STREAM_RESULTS_ +# include // NOLINT +# include // NOLINT +#endif + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +// 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 +// 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. + +// Utility functions and classes used by the Google C++ testing framework. +// +// Author: wan@google.com (Zhanyong Wan) +// +// This file contains purely Google Test's internal implementation. Please +// DO NOT #INCLUDE IT IN A USER PROGRAM. + +#ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_ +#define GTEST_SRC_GTEST_INTERNAL_INL_H_ + +// GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is +// part of Google Test's implementation; otherwise it's undefined. +#if !GTEST_IMPLEMENTATION_ +// A user is trying to include this from his code - just say no. +# error "gtest-internal-inl.h is part of Google Test's internal implementation." +# error "It must not be included except by Google Test itself." +#endif // GTEST_IMPLEMENTATION_ + +#ifndef _WIN32_WCE +# include +#endif // !_WIN32_WCE +#include +#include // For strtoll/_strtoul64/malloc/free. +#include // For memmove. + +#include +#include +#include + + +#if GTEST_CAN_STREAM_RESULTS_ +# include // NOLINT +# include // NOLINT +#endif + +#if GTEST_OS_WINDOWS +# include // NOLINT +#endif // GTEST_OS_WINDOWS + + +namespace testing { + +// Declares the flags. +// +// We don't want the users to modify this flag in the code, but want +// Google Test's own unit tests to be able to access it. Therefore we +// declare it here as opposed to in gtest.h. +GTEST_DECLARE_bool_(death_test_use_fork); + +namespace internal { + +// The value of GetTestTypeId() as seen from within the Google Test +// library. This is solely for testing GetTestTypeId(). +GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest; + +// Names of the flags (needed for parsing Google Test flags). +const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests"; +const char kBreakOnFailureFlag[] = "break_on_failure"; +const char kCatchExceptionsFlag[] = "catch_exceptions"; +const char kColorFlag[] = "color"; +const char kFilterFlag[] = "filter"; +const char kListTestsFlag[] = "list_tests"; +const char kOutputFlag[] = "output"; +const char kPrintTimeFlag[] = "print_time"; +const char kRandomSeedFlag[] = "random_seed"; +const char kRepeatFlag[] = "repeat"; +const char kShuffleFlag[] = "shuffle"; +const char kStackTraceDepthFlag[] = "stack_trace_depth"; +const char kStreamResultToFlag[] = "stream_result_to"; +const char kThrowOnFailureFlag[] = "throw_on_failure"; + +// A valid random seed must be in [1, kMaxRandomSeed]. +const int kMaxRandomSeed = 99999; + +// g_help_flag is true iff the --help flag or an equivalent form is +// specified on the command line. +GTEST_API_ extern bool g_help_flag; + +// Returns the current time in milliseconds. +GTEST_API_ TimeInMillis GetTimeInMillis(); + +// Returns true iff Google Test should use colors in the output. +GTEST_API_ bool ShouldUseColor(bool stdout_is_tty); + +// Formats the given time in milliseconds as seconds. +GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms); + +// Converts the given time in milliseconds to a date string in the ISO 8601 +// format, without the timezone information. N.B.: due to the use the +// non-reentrant localtime() function, this function is not thread safe. Do +// not use it in any code that can be called from multiple threads. +GTEST_API_ std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms); + +// Parses a string for an Int32 flag, in the form of "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +GTEST_API_ bool ParseInt32Flag( + const char* str, const char* flag, Int32* value); + +// Returns a random seed in range [1, kMaxRandomSeed] based on the +// given --gtest_random_seed flag value. +inline int GetRandomSeedFromFlag(Int32 random_seed_flag) { + const unsigned int raw_seed = (random_seed_flag == 0) ? + static_cast(GetTimeInMillis()) : + static_cast(random_seed_flag); + + // Normalizes the actual seed to range [1, kMaxRandomSeed] such that + // it's easy to type. + const int normalized_seed = + static_cast((raw_seed - 1U) % + static_cast(kMaxRandomSeed)) + 1; + return normalized_seed; +} + +// Returns the first valid random seed after 'seed'. The behavior is +// undefined if 'seed' is invalid. The seed after kMaxRandomSeed is +// considered to be 1. +inline int GetNextRandomSeed(int seed) { + GTEST_CHECK_(1 <= seed && seed <= kMaxRandomSeed) + << "Invalid random seed " << seed << " - must be in [1, " + << kMaxRandomSeed << "]."; + const int next_seed = seed + 1; + return (next_seed > kMaxRandomSeed) ? 1 : next_seed; +} + +// This class saves the values of all Google Test flags in its c'tor, and +// restores them in its d'tor. +class GTestFlagSaver { + public: + // The c'tor. + GTestFlagSaver() { + also_run_disabled_tests_ = GTEST_FLAG(also_run_disabled_tests); + break_on_failure_ = GTEST_FLAG(break_on_failure); + catch_exceptions_ = GTEST_FLAG(catch_exceptions); + color_ = GTEST_FLAG(color); + death_test_style_ = GTEST_FLAG(death_test_style); + death_test_use_fork_ = GTEST_FLAG(death_test_use_fork); + filter_ = GTEST_FLAG(filter); + internal_run_death_test_ = GTEST_FLAG(internal_run_death_test); + list_tests_ = GTEST_FLAG(list_tests); + output_ = GTEST_FLAG(output); + print_time_ = GTEST_FLAG(print_time); + random_seed_ = GTEST_FLAG(random_seed); + repeat_ = GTEST_FLAG(repeat); + shuffle_ = GTEST_FLAG(shuffle); + stack_trace_depth_ = GTEST_FLAG(stack_trace_depth); + stream_result_to_ = GTEST_FLAG(stream_result_to); + throw_on_failure_ = GTEST_FLAG(throw_on_failure); + } + + // The d'tor is not virtual. DO NOT INHERIT FROM THIS CLASS. + ~GTestFlagSaver() { + GTEST_FLAG(also_run_disabled_tests) = also_run_disabled_tests_; + GTEST_FLAG(break_on_failure) = break_on_failure_; + GTEST_FLAG(catch_exceptions) = catch_exceptions_; + GTEST_FLAG(color) = color_; + GTEST_FLAG(death_test_style) = death_test_style_; + GTEST_FLAG(death_test_use_fork) = death_test_use_fork_; + GTEST_FLAG(filter) = filter_; + GTEST_FLAG(internal_run_death_test) = internal_run_death_test_; + GTEST_FLAG(list_tests) = list_tests_; + GTEST_FLAG(output) = output_; + GTEST_FLAG(print_time) = print_time_; + GTEST_FLAG(random_seed) = random_seed_; + GTEST_FLAG(repeat) = repeat_; + GTEST_FLAG(shuffle) = shuffle_; + GTEST_FLAG(stack_trace_depth) = stack_trace_depth_; + GTEST_FLAG(stream_result_to) = stream_result_to_; + GTEST_FLAG(throw_on_failure) = throw_on_failure_; + } + + private: + // Fields for saving the original values of flags. + bool also_run_disabled_tests_; + bool break_on_failure_; + bool catch_exceptions_; + std::string color_; + std::string death_test_style_; + bool death_test_use_fork_; + std::string filter_; + std::string internal_run_death_test_; + bool list_tests_; + std::string output_; + bool print_time_; + internal::Int32 random_seed_; + internal::Int32 repeat_; + bool shuffle_; + internal::Int32 stack_trace_depth_; + std::string stream_result_to_; + bool throw_on_failure_; +} GTEST_ATTRIBUTE_UNUSED_; + +// Converts a Unicode code point to a narrow string in UTF-8 encoding. +// code_point parameter is of type UInt32 because wchar_t may not be +// wide enough to contain a code point. +// If the code_point is not a valid Unicode code point +// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted +// to "(Invalid Unicode 0xXXXXXXXX)". +GTEST_API_ std::string CodePointToUtf8(UInt32 code_point); + +// Converts a wide string to a narrow string in UTF-8 encoding. +// The wide string is assumed to have the following encoding: +// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS) +// UTF-32 if sizeof(wchar_t) == 4 (on Linux) +// Parameter str points to a null-terminated wide string. +// Parameter num_chars may additionally limit the number +// of wchar_t characters processed. -1 is used when the entire string +// should be processed. +// If the string contains code points that are not valid Unicode code points +// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output +// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding +// and contains invalid UTF-16 surrogate pairs, values in those pairs +// will be encoded as individual Unicode characters from Basic Normal Plane. +GTEST_API_ std::string WideStringToUtf8(const wchar_t* str, int num_chars); + +// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file +// if the variable is present. If a file already exists at this location, this +// function will write over it. If the variable is present, but the file cannot +// be created, prints an error and exits. +void WriteToShardStatusFileIfNeeded(); + +// Checks whether sharding is enabled by examining the relevant +// environment variable values. If the variables are present, +// but inconsistent (e.g., shard_index >= total_shards), prints +// an error and exits. If in_subprocess_for_death_test, sharding is +// disabled because it must only be applied to the original test +// process. Otherwise, we could filter out death tests we intended to execute. +GTEST_API_ bool ShouldShard(const char* total_shards_str, + const char* shard_index_str, + bool in_subprocess_for_death_test); + +// Parses the environment variable var as an Int32. If it is unset, +// returns default_val. If it is not an Int32, prints an error and +// and aborts. +GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val); + +// Given the total number of shards, the shard index, and the test id, +// returns true iff the test should be run on this shard. The test id is +// some arbitrary but unique non-negative integer assigned to each test +// method. Assumes that 0 <= shard_index < total_shards. +GTEST_API_ bool ShouldRunTestOnShard( + int total_shards, int shard_index, int test_id); + +// STL container utilities. + +// Returns the number of elements in the given container that satisfy +// the given predicate. +template +inline int CountIf(const Container& c, Predicate predicate) { + // Implemented as an explicit loop since std::count_if() in libCstd on + // Solaris has a non-standard signature. + int count = 0; + for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) { + if (predicate(*it)) + ++count; + } + return count; +} + +// Applies a function/functor to each element in the container. +template +void ForEach(const Container& c, Functor functor) { + std::for_each(c.begin(), c.end(), functor); +} + +// Returns the i-th element of the vector, or default_value if i is not +// in range [0, v.size()). +template +inline E GetElementOr(const std::vector& v, int i, E default_value) { + return (i < 0 || i >= static_cast(v.size())) ? default_value : v[i]; +} + +// Performs an in-place shuffle of a range of the vector's elements. +// 'begin' and 'end' are element indices as an STL-style range; +// i.e. [begin, end) are shuffled, where 'end' == size() means to +// shuffle to the end of the vector. +template +void ShuffleRange(internal::Random* random, int begin, int end, + std::vector* v) { + const int size = static_cast(v->size()); + GTEST_CHECK_(0 <= begin && begin <= size) + << "Invalid shuffle range start " << begin << ": must be in range [0, " + << size << "]."; + GTEST_CHECK_(begin <= end && end <= size) + << "Invalid shuffle range finish " << end << ": must be in range [" + << begin << ", " << size << "]."; + + // Fisher-Yates shuffle, from + // http://en.wikipedia.org/wiki/Fisher-Yates_shuffle + for (int range_width = end - begin; range_width >= 2; range_width--) { + const int last_in_range = begin + range_width - 1; + const int selected = begin + random->Generate(range_width); + std::swap((*v)[selected], (*v)[last_in_range]); + } +} + +// Performs an in-place shuffle of the vector's elements. +template +inline void Shuffle(internal::Random* random, std::vector* v) { + ShuffleRange(random, 0, static_cast(v->size()), v); +} + +// A function for deleting an object. Handy for being used as a +// functor. +template +static void Delete(T* x) { + delete x; +} + +// A predicate that checks the key of a TestProperty against a known key. +// +// TestPropertyKeyIs is copyable. +class TestPropertyKeyIs { + public: + // Constructor. + // + // TestPropertyKeyIs has NO default constructor. + explicit TestPropertyKeyIs(const std::string& key) : key_(key) {} + + // Returns true iff the test name of test property matches on key_. + bool operator()(const TestProperty& test_property) const { + return test_property.key() == key_; + } + + private: + std::string key_; +}; + +// Class UnitTestOptions. +// +// This class contains functions for processing options the user +// specifies when running the tests. It has only static members. +// +// In most cases, the user can specify an option using either an +// environment variable or a command line flag. E.g. you can set the +// test filter using either GTEST_FILTER or --gtest_filter. If both +// the variable and the flag are present, the latter overrides the +// former. +class GTEST_API_ UnitTestOptions { + public: + // Functions for processing the gtest_output flag. + + // Returns the output format, or "" for normal printed output. + static std::string GetOutputFormat(); + + // Returns the absolute path of the requested output file, or the + // default (test_detail.xml in the original working directory) if + // none was explicitly specified. + static std::string GetAbsolutePathToOutputFile(); + + // Functions for processing the gtest_filter flag. + + // Returns true iff the wildcard pattern matches the string. The + // first ':' or '\0' character in pattern marks the end of it. + // + // This recursive algorithm isn't very efficient, but is clear and + // works well enough for matching test names, which are short. + static bool PatternMatchesString(const char *pattern, const char *str); + + // Returns true iff the user-specified filter matches the test case + // name and the test name. + static bool FilterMatchesTest(const std::string &test_case_name, + const std::string &test_name); + +#if GTEST_OS_WINDOWS + // Function for supporting the gtest_catch_exception flag. + + // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the + // given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise. + // This function is useful as an __except condition. + static int GTestShouldProcessSEH(DWORD exception_code); +#endif // GTEST_OS_WINDOWS + + // Returns true if "name" matches the ':' separated list of glob-style + // filters in "filter". + static bool MatchesFilter(const std::string& name, const char* filter); +}; + +// Returns the current application's name, removing directory path if that +// is present. Used by UnitTestOptions::GetOutputFile. +GTEST_API_ FilePath GetCurrentExecutableName(); + +// The role interface for getting the OS stack trace as a string. +class OsStackTraceGetterInterface { + public: + OsStackTraceGetterInterface() {} + virtual ~OsStackTraceGetterInterface() {} + + // Returns the current OS stack trace as an std::string. Parameters: + // + // max_depth - the maximum number of stack frames to be included + // in the trace. + // skip_count - the number of top frames to be skipped; doesn't count + // against max_depth. + virtual string CurrentStackTrace(int max_depth, int skip_count) = 0; + + // UponLeavingGTest() should be called immediately before Google Test calls + // user code. It saves some information about the current stack that + // CurrentStackTrace() will use to find and hide Google Test stack frames. + virtual void UponLeavingGTest() = 0; + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface); +}; + +// A working implementation of the OsStackTraceGetterInterface interface. +class OsStackTraceGetter : public OsStackTraceGetterInterface { + public: + OsStackTraceGetter() : caller_frame_(NULL) {} + + virtual string CurrentStackTrace(int max_depth, int skip_count) + GTEST_LOCK_EXCLUDED_(mutex_); + + virtual void UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_); + + // This string is inserted in place of stack frames that are part of + // Google Test's implementation. + static const char* const kElidedFramesMarker; + + private: + Mutex mutex_; // protects all internal state + + // We save the stack frame below the frame that calls user code. + // We do this because the address of the frame immediately below + // the user code changes between the call to UponLeavingGTest() + // and any calls to CurrentStackTrace() from within the user code. + void* caller_frame_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter); +}; + +// Information about a Google Test trace point. +struct TraceInfo { + const char* file; + int line; + std::string message; +}; + +// This is the default global test part result reporter used in UnitTestImpl. +// This class should only be used by UnitTestImpl. +class DefaultGlobalTestPartResultReporter + : public TestPartResultReporterInterface { + public: + explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test); + // Implements the TestPartResultReporterInterface. Reports the test part + // result in the current test. + virtual void ReportTestPartResult(const TestPartResult& result); + + private: + UnitTestImpl* const unit_test_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultGlobalTestPartResultReporter); +}; + +// This is the default per thread test part result reporter used in +// UnitTestImpl. This class should only be used by UnitTestImpl. +class DefaultPerThreadTestPartResultReporter + : public TestPartResultReporterInterface { + public: + explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test); + // Implements the TestPartResultReporterInterface. The implementation just + // delegates to the current global test part result reporter of *unit_test_. + virtual void ReportTestPartResult(const TestPartResult& result); + + private: + UnitTestImpl* const unit_test_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultPerThreadTestPartResultReporter); +}; + +// The private implementation of the UnitTest class. We don't protect +// the methods under a mutex, as this class is not accessible by a +// user and the UnitTest class that delegates work to this class does +// proper locking. +class GTEST_API_ UnitTestImpl { + public: + explicit UnitTestImpl(UnitTest* parent); + virtual ~UnitTestImpl(); + + // There are two different ways to register your own TestPartResultReporter. + // You can register your own repoter to listen either only for test results + // from the current thread or for results from all threads. + // By default, each per-thread test result repoter just passes a new + // TestPartResult to the global test result reporter, which registers the + // test part result for the currently running test. + + // Returns the global test part result reporter. + TestPartResultReporterInterface* GetGlobalTestPartResultReporter(); + + // Sets the global test part result reporter. + void SetGlobalTestPartResultReporter( + TestPartResultReporterInterface* reporter); + + // Returns the test part result reporter for the current thread. + TestPartResultReporterInterface* GetTestPartResultReporterForCurrentThread(); + + // Sets the test part result reporter for the current thread. + void SetTestPartResultReporterForCurrentThread( + TestPartResultReporterInterface* reporter); + + // Gets the number of successful test cases. + int successful_test_case_count() const; + + // Gets the number of failed test cases. + int failed_test_case_count() const; + + // Gets the number of all test cases. + int total_test_case_count() const; + + // Gets the number of all test cases that contain at least one test + // that should run. + int test_case_to_run_count() const; + + // Gets the number of successful tests. + int successful_test_count() const; + + // Gets the number of failed tests. + int failed_test_count() const; + + // Gets the number of disabled tests that will be reported in the XML report. + int reportable_disabled_test_count() const; + + // Gets the number of disabled tests. + int disabled_test_count() const; + + // Gets the number of tests to be printed in the XML report. + int reportable_test_count() const; + + // Gets the number of all tests. + int total_test_count() const; + + // Gets the number of tests that should run. + int test_to_run_count() const; + + // Gets the time of the test program start, in ms from the start of the + // UNIX epoch. + TimeInMillis start_timestamp() const { return start_timestamp_; } + + // Gets the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns true iff the unit test passed (i.e. all test cases passed). + bool Passed() const { return !Failed(); } + + // Returns true iff the unit test failed (i.e. some test case failed + // or something outside of all tests failed). + bool Failed() const { + return failed_test_case_count() > 0 || ad_hoc_test_result()->Failed(); + } + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + const TestCase* GetTestCase(int i) const { + const int index = GetElementOr(test_case_indices_, i, -1); + return index < 0 ? NULL : test_cases_[i]; + } + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + TestCase* GetMutableTestCase(int i) { + const int index = GetElementOr(test_case_indices_, i, -1); + return index < 0 ? NULL : test_cases_[index]; + } + + // Provides access to the event listener list. + TestEventListeners* listeners() { return &listeners_; } + + // Returns the TestResult for the test that's currently running, or + // the TestResult for the ad hoc test if no test is running. + TestResult* current_test_result(); + + // Returns the TestResult for the ad hoc test. + const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; } + + // Sets the OS stack trace getter. + // + // Does nothing if the input and the current OS stack trace getter + // are the same; otherwise, deletes the old getter and makes the + // input the current getter. + void set_os_stack_trace_getter(OsStackTraceGetterInterface* getter); + + // Returns the current OS stack trace getter if it is not NULL; + // otherwise, creates an OsStackTraceGetter, makes it the current + // getter, and returns it. + OsStackTraceGetterInterface* os_stack_trace_getter(); + + // Returns the current OS stack trace as an std::string. + // + // The maximum number of stack frames to be included is specified by + // the gtest_stack_trace_depth flag. The skip_count parameter + // specifies the number of top frames to be skipped, which doesn't + // count against the number of frames to be included. + // + // For example, if Foo() calls Bar(), which in turn calls + // CurrentOsStackTraceExceptTop(1), Foo() will be included in the + // trace but Bar() and CurrentOsStackTraceExceptTop() won't. + std::string CurrentOsStackTraceExceptTop(int skip_count) GTEST_NO_INLINE_; + + // Finds and returns a TestCase with the given name. If one doesn't + // exist, creates one and returns it. + // + // Arguments: + // + // test_case_name: name of the test case + // type_param: the name of the test's type parameter, or NULL if + // this is not a typed or a type-parameterized test. + // set_up_tc: pointer to the function that sets up the test case + // tear_down_tc: pointer to the function that tears down the test case + TestCase* GetTestCase(const char* test_case_name, + const char* type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc); + + // Adds a TestInfo to the unit test. + // + // Arguments: + // + // set_up_tc: pointer to the function that sets up the test case + // tear_down_tc: pointer to the function that tears down the test case + // test_info: the TestInfo object + void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc, + TestInfo* test_info) { + // In order to support thread-safe death tests, we need to + // remember the original working directory when the test program + // was first invoked. We cannot do this in RUN_ALL_TESTS(), as + // the user may have changed the current directory before calling + // RUN_ALL_TESTS(). Therefore we capture the current directory in + // AddTestInfo(), which is called to register a TEST or TEST_F + // before main() is reached. + if (original_working_dir_.IsEmpty()) { + original_working_dir_.Set(FilePath::GetCurrentDir()); + GTEST_CHECK_(!original_working_dir_.IsEmpty()) + << "Failed to get the current working directory."; + } + + GetTestCase(test_info->test_case_name(), + test_info->type_param(), + set_up_tc, + tear_down_tc)->AddTestInfo(test_info); + } + +#if GTEST_HAS_PARAM_TEST + // Returns ParameterizedTestCaseRegistry object used to keep track of + // value-parameterized tests and instantiate and register them. + internal::ParameterizedTestCaseRegistry& parameterized_test_registry() { + return parameterized_test_registry_; + } +#endif // GTEST_HAS_PARAM_TEST + + // Sets the TestCase object for the test that's currently running. + void set_current_test_case(TestCase* a_current_test_case) { + current_test_case_ = a_current_test_case; + } + + // Sets the TestInfo object for the test that's currently running. If + // current_test_info is NULL, the assertion results will be stored in + // ad_hoc_test_result_. + void set_current_test_info(TestInfo* a_current_test_info) { + current_test_info_ = a_current_test_info; + } + + // Registers all parameterized tests defined using TEST_P and + // INSTANTIATE_TEST_CASE_P, creating regular tests for each test/parameter + // combination. This method can be called more then once; it has guards + // protecting from registering the tests more then once. If + // value-parameterized tests are disabled, RegisterParameterizedTests is + // present but does nothing. + void RegisterParameterizedTests(); + + // Runs all tests in this UnitTest object, prints the result, and + // returns true if all tests are successful. If any exception is + // thrown during a test, this test is considered to be failed, but + // the rest of the tests will still be run. + bool RunAllTests(); + + // Clears the results of all tests, except the ad hoc tests. + void ClearNonAdHocTestResult() { + ForEach(test_cases_, TestCase::ClearTestCaseResult); + } + + // Clears the results of ad-hoc test assertions. + void ClearAdHocTestResult() { + ad_hoc_test_result_.Clear(); + } + + // Adds a TestProperty to the current TestResult object when invoked in a + // context of a test or a test case, or to the global property set. If the + // result already contains a property with the same key, the value will be + // updated. + void RecordProperty(const TestProperty& test_property); + + enum ReactionToSharding { + HONOR_SHARDING_PROTOCOL, + IGNORE_SHARDING_PROTOCOL + }; + + // Matches the full name of each test against the user-specified + // filter to decide whether the test should run, then records the + // result in each TestCase and TestInfo object. + // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests + // based on sharding variables in the environment. + // Returns the number of tests that should run. + int FilterTests(ReactionToSharding shard_tests); + + // Prints the names of the tests matching the user-specified filter flag. + void ListTestsMatchingFilter(); + + const TestCase* current_test_case() const { return current_test_case_; } + TestInfo* current_test_info() { return current_test_info_; } + const TestInfo* current_test_info() const { return current_test_info_; } + + // Returns the vector of environments that need to be set-up/torn-down + // before/after the tests are run. + std::vector& environments() { return environments_; } + + // Getters for the per-thread Google Test trace stack. + std::vector& gtest_trace_stack() { + return *(gtest_trace_stack_.pointer()); + } + const std::vector& gtest_trace_stack() const { + return gtest_trace_stack_.get(); + } + +#if GTEST_HAS_DEATH_TEST + void InitDeathTestSubprocessControlInfo() { + internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag()); + } + // Returns a pointer to the parsed --gtest_internal_run_death_test + // flag, or NULL if that flag was not specified. + // This information is useful only in a death test child process. + // Must not be called before a call to InitGoogleTest. + const InternalRunDeathTestFlag* internal_run_death_test_flag() const { + return internal_run_death_test_flag_.get(); + } + + // Returns a pointer to the current death test factory. + internal::DeathTestFactory* death_test_factory() { + return death_test_factory_.get(); + } + + void SuppressTestEventsIfInSubprocess(); + + friend class ReplaceDeathTestFactory; +#endif // GTEST_HAS_DEATH_TEST + + // Initializes the event listener performing XML output as specified by + // UnitTestOptions. Must not be called before InitGoogleTest. + void ConfigureXmlOutput(); + +#if GTEST_CAN_STREAM_RESULTS_ + // Initializes the event listener for streaming test results to a socket. + // Must not be called before InitGoogleTest. + void ConfigureStreamingOutput(); +#endif + + // Performs initialization dependent upon flag values obtained in + // ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to + // ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest + // this function is also called from RunAllTests. Since this function can be + // called more than once, it has to be idempotent. + void PostFlagParsingInit(); + + // Gets the random seed used at the start of the current test iteration. + int random_seed() const { return random_seed_; } + + // Gets the random number generator. + internal::Random* random() { return &random_; } + + // Shuffles all test cases, and the tests within each test case, + // making sure that death tests are still run first. + void ShuffleTests(); + + // Restores the test cases and tests to their order before the first shuffle. + void UnshuffleTests(); + + // Returns the value of GTEST_FLAG(catch_exceptions) at the moment + // UnitTest::Run() starts. + bool catch_exceptions() const { return catch_exceptions_; } + + private: + friend class ::testing::UnitTest; + + // Used by UnitTest::Run() to capture the state of + // GTEST_FLAG(catch_exceptions) at the moment it starts. + void set_catch_exceptions(bool value) { catch_exceptions_ = value; } + + // The UnitTest object that owns this implementation object. + UnitTest* const parent_; + + // The working directory when the first TEST() or TEST_F() was + // executed. + internal::FilePath original_working_dir_; + + // The default test part result reporters. + DefaultGlobalTestPartResultReporter default_global_test_part_result_reporter_; + DefaultPerThreadTestPartResultReporter + default_per_thread_test_part_result_reporter_; + + // Points to (but doesn't own) the global test part result reporter. + TestPartResultReporterInterface* global_test_part_result_repoter_; + + // Protects read and write access to global_test_part_result_reporter_. + internal::Mutex global_test_part_result_reporter_mutex_; + + // Points to (but doesn't own) the per-thread test part result reporter. + internal::ThreadLocal + per_thread_test_part_result_reporter_; + + // The vector of environments that need to be set-up/torn-down + // before/after the tests are run. + std::vector environments_; + + // The vector of TestCases in their original order. It owns the + // elements in the vector. + std::vector test_cases_; + + // Provides a level of indirection for the test case list to allow + // easy shuffling and restoring the test case order. The i-th + // element of this vector is the index of the i-th test case in the + // shuffled order. + std::vector test_case_indices_; + +#if GTEST_HAS_PARAM_TEST + // ParameterizedTestRegistry object used to register value-parameterized + // tests. + internal::ParameterizedTestCaseRegistry parameterized_test_registry_; + + // Indicates whether RegisterParameterizedTests() has been called already. + bool parameterized_tests_registered_; +#endif // GTEST_HAS_PARAM_TEST + + // Index of the last death test case registered. Initially -1. + int last_death_test_case_; + + // This points to the TestCase for the currently running test. It + // changes as Google Test goes through one test case after another. + // When no test is running, this is set to NULL and Google Test + // stores assertion results in ad_hoc_test_result_. Initially NULL. + TestCase* current_test_case_; + + // This points to the TestInfo for the currently running test. It + // changes as Google Test goes through one test after another. When + // no test is running, this is set to NULL and Google Test stores + // assertion results in ad_hoc_test_result_. Initially NULL. + TestInfo* current_test_info_; + + // Normally, a user only writes assertions inside a TEST or TEST_F, + // or inside a function called by a TEST or TEST_F. Since Google + // Test keeps track of which test is current running, it can + // associate such an assertion with the test it belongs to. + // + // If an assertion is encountered when no TEST or TEST_F is running, + // Google Test attributes the assertion result to an imaginary "ad hoc" + // test, and records the result in ad_hoc_test_result_. + TestResult ad_hoc_test_result_; + + // The list of event listeners that can be used to track events inside + // Google Test. + TestEventListeners listeners_; + + // The OS stack trace getter. Will be deleted when the UnitTest + // object is destructed. By default, an OsStackTraceGetter is used, + // but the user can set this field to use a custom getter if that is + // desired. + OsStackTraceGetterInterface* os_stack_trace_getter_; + + // True iff PostFlagParsingInit() has been called. + bool post_flag_parse_init_performed_; + + // The random number seed used at the beginning of the test run. + int random_seed_; + + // Our random number generator. + internal::Random random_; + + // The time of the test program start, in ms from the start of the + // UNIX epoch. + TimeInMillis start_timestamp_; + + // How long the test took to run, in milliseconds. + TimeInMillis elapsed_time_; + +#if GTEST_HAS_DEATH_TEST + // The decomposed components of the gtest_internal_run_death_test flag, + // parsed when RUN_ALL_TESTS is called. + internal::scoped_ptr internal_run_death_test_flag_; + internal::scoped_ptr death_test_factory_; +#endif // GTEST_HAS_DEATH_TEST + + // A per-thread stack of traces created by the SCOPED_TRACE() macro. + internal::ThreadLocal > gtest_trace_stack_; + + // The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests() + // starts. + bool catch_exceptions_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl); +}; // class UnitTestImpl + +// Convenience function for accessing the global UnitTest +// implementation object. +inline UnitTestImpl* GetUnitTestImpl() { + return UnitTest::GetInstance()->impl(); +} + +#if GTEST_USES_SIMPLE_RE + +// Internal helper functions for implementing the simple regular +// expression matcher. +GTEST_API_ bool IsInSet(char ch, const char* str); +GTEST_API_ bool IsAsciiDigit(char ch); +GTEST_API_ bool IsAsciiPunct(char ch); +GTEST_API_ bool IsRepeat(char ch); +GTEST_API_ bool IsAsciiWhiteSpace(char ch); +GTEST_API_ bool IsAsciiWordChar(char ch); +GTEST_API_ bool IsValidEscape(char ch); +GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch); +GTEST_API_ bool ValidateRegex(const char* regex); +GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str); +GTEST_API_ bool MatchRepetitionAndRegexAtHead( + bool escaped, char ch, char repeat, const char* regex, const char* str); +GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str); + +#endif // GTEST_USES_SIMPLE_RE + +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. +GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv); +GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv); + +#if GTEST_HAS_DEATH_TEST + +// Returns the message describing the last system error, regardless of the +// platform. +GTEST_API_ std::string GetLastErrnoDescription(); + +# if GTEST_OS_WINDOWS +// Provides leak-safe Windows kernel handle ownership. +class AutoHandle { + public: + AutoHandle() : handle_(INVALID_HANDLE_VALUE) {} + explicit AutoHandle(HANDLE handle) : handle_(handle) {} + + ~AutoHandle() { Reset(); } + + HANDLE Get() const { return handle_; } + void Reset() { Reset(INVALID_HANDLE_VALUE); } + void Reset(HANDLE handle) { + if (handle != handle_) { + if (handle_ != INVALID_HANDLE_VALUE) + ::CloseHandle(handle_); + handle_ = handle; + } + } + + private: + HANDLE handle_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle); +}; +# endif // GTEST_OS_WINDOWS + +// Attempts to parse a string into a positive integer pointed to by the +// number parameter. Returns true if that is possible. +// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use +// it here. +template +bool ParseNaturalNumber(const ::std::string& str, Integer* number) { + // Fail fast if the given string does not begin with a digit; + // this bypasses strtoXXX's "optional leading whitespace and plus + // or minus sign" semantics, which are undesirable here. + if (str.empty() || !IsDigit(str[0])) { + return false; + } + errno = 0; + + char* end; + // BiggestConvertible is the largest integer type that system-provided + // string-to-number conversion routines can return. + +# if GTEST_OS_WINDOWS && !defined(__GNUC__) + + // MSVC and C++ Builder define __int64 instead of the standard long long. + typedef unsigned __int64 BiggestConvertible; + const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10); + +# else + + typedef unsigned long long BiggestConvertible; // NOLINT + const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10); + +# endif // GTEST_OS_WINDOWS && !defined(__GNUC__) + + const bool parse_success = *end == '\0' && errno == 0; + + // TODO(vladl@google.com): Convert this to compile time assertion when it is + // available. + GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed)); + + const Integer result = static_cast(parsed); + if (parse_success && static_cast(result) == parsed) { + *number = result; + return true; + } + return false; +} +#endif // GTEST_HAS_DEATH_TEST + +// TestResult contains some private methods that should be hidden from +// Google Test user but are required for testing. This class allow our tests +// to access them. +// +// This class is supplied only for the purpose of testing Google Test's own +// constructs. Do not use it in user tests, either directly or indirectly. +class TestResultAccessor { + public: + static void RecordProperty(TestResult* test_result, + const std::string& xml_element, + const TestProperty& property) { + test_result->RecordProperty(xml_element, property); + } + + static void ClearTestPartResults(TestResult* test_result) { + test_result->ClearTestPartResults(); + } + + static const std::vector& test_part_results( + const TestResult& test_result) { + return test_result.test_part_results(); + } +}; + +#if GTEST_CAN_STREAM_RESULTS_ + +// Streams test results to the given port on the given host machine. +class StreamingListener : public EmptyTestEventListener { + public: + // Abstract base class for writing strings to a socket. + class AbstractSocketWriter { + public: + virtual ~AbstractSocketWriter() {} + + // Sends a string to the socket. + virtual void Send(const string& message) = 0; + + // Closes the socket. + virtual void CloseConnection() {} + + // Sends a string and a newline to the socket. + void SendLn(const string& message) { + Send(message + "\n"); + } + }; + + // Concrete class for actually writing strings to a socket. + class SocketWriter : public AbstractSocketWriter { + public: + SocketWriter(const string& host, const string& port) + : sockfd_(-1), host_name_(host), port_num_(port) { + MakeConnection(); + } + + virtual ~SocketWriter() { + if (sockfd_ != -1) + CloseConnection(); + } + + // Sends a string to the socket. + virtual void Send(const string& message) { + GTEST_CHECK_(sockfd_ != -1) + << "Send() can be called only when there is a connection."; + + const int len = static_cast(message.length()); + if (write(sockfd_, message.c_str(), len) != len) { + GTEST_LOG_(WARNING) + << "stream_result_to: failed to stream to " + << host_name_ << ":" << port_num_; + } + } + + private: + // Creates a client socket and connects to the server. + void MakeConnection(); + + // Closes the socket. + void CloseConnection() { + GTEST_CHECK_(sockfd_ != -1) + << "CloseConnection() can be called only when there is a connection."; + + close(sockfd_); + sockfd_ = -1; + } + + int sockfd_; // socket file descriptor + const string host_name_; + const string port_num_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(SocketWriter); + }; // class SocketWriter + + // Escapes '=', '&', '%', and '\n' characters in str as "%xx". + static string UrlEncode(const char* str); + + StreamingListener(const string& host, const string& port) + : socket_writer_(new SocketWriter(host, port)) { Start(); } + + explicit StreamingListener(AbstractSocketWriter* socket_writer) + : socket_writer_(socket_writer) { Start(); } + + void OnTestProgramStart(const UnitTest& /* unit_test */) { + SendLn("event=TestProgramStart"); + } + + void OnTestProgramEnd(const UnitTest& unit_test) { + // Note that Google Test current only report elapsed time for each + // test iteration, not for the entire test program. + SendLn("event=TestProgramEnd&passed=" + FormatBool(unit_test.Passed())); + + // Notify the streaming server to stop. + socket_writer_->CloseConnection(); + } + + void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) { + SendLn("event=TestIterationStart&iteration=" + + StreamableToString(iteration)); + } + + void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) { + SendLn("event=TestIterationEnd&passed=" + + FormatBool(unit_test.Passed()) + "&elapsed_time=" + + StreamableToString(unit_test.elapsed_time()) + "ms"); + } + + void OnTestCaseStart(const TestCase& test_case) { + SendLn(std::string("event=TestCaseStart&name=") + test_case.name()); + } + + void OnTestCaseEnd(const TestCase& test_case) { + SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed()) + + "&elapsed_time=" + StreamableToString(test_case.elapsed_time()) + + "ms"); + } + + void OnTestStart(const TestInfo& test_info) { + SendLn(std::string("event=TestStart&name=") + test_info.name()); + } + + void OnTestEnd(const TestInfo& test_info) { + SendLn("event=TestEnd&passed=" + + FormatBool((test_info.result())->Passed()) + + "&elapsed_time=" + + StreamableToString((test_info.result())->elapsed_time()) + "ms"); + } + + void OnTestPartResult(const TestPartResult& test_part_result) { + const char* file_name = test_part_result.file_name(); + if (file_name == NULL) + file_name = ""; + SendLn("event=TestPartResult&file=" + UrlEncode(file_name) + + "&line=" + StreamableToString(test_part_result.line_number()) + + "&message=" + UrlEncode(test_part_result.message())); + } + + private: + // Sends the given message and a newline to the socket. + void SendLn(const string& message) { socket_writer_->SendLn(message); } + + // Called at the start of streaming to notify the receiver what + // protocol we are using. + void Start() { SendLn("gtest_streaming_protocol_version=1.0"); } + + string FormatBool(bool value) { return value ? "1" : "0"; } + + const scoped_ptr socket_writer_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener); +}; // class StreamingListener + +#endif // GTEST_CAN_STREAM_RESULTS_ + +} // namespace internal +} // namespace testing + +#endif // GTEST_SRC_GTEST_INTERNAL_INL_H_ +#undef GTEST_IMPLEMENTATION_ + +#if GTEST_OS_WINDOWS +# define vsnprintf _vsnprintf +#endif // GTEST_OS_WINDOWS + +namespace testing { + +using internal::CountIf; +using internal::ForEach; +using internal::GetElementOr; +using internal::Shuffle; + +// Constants. + +// A test whose test case name or test name matches this filter is +// disabled and not run. +static const char kDisableTestFilter[] = "DISABLED_*:*/DISABLED_*"; + +// A test case whose name matches this filter is considered a death +// test case and will be run before test cases whose name doesn't +// match this filter. +static const char kDeathTestCaseFilter[] = "*DeathTest:*DeathTest/*"; + +// A test filter that matches everything. +static const char kUniversalFilter[] = "*"; + +// The default output file for XML output. +static const char kDefaultOutputFile[] = "test_detail.xml"; + +// The environment variable name for the test shard index. +static const char kTestShardIndex[] = "GTEST_SHARD_INDEX"; +// The environment variable name for the total number of test shards. +static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS"; +// The environment variable name for the test shard status file. +static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE"; + +namespace internal { + +// The text used in failure messages to indicate the start of the +// stack trace. +const char kStackTraceMarker[] = "\nStack trace:\n"; + +// g_help_flag is true iff the --help flag or an equivalent form is +// specified on the command line. +bool g_help_flag = false; + +} // namespace internal + +static const char* GetDefaultFilter() { + return kUniversalFilter; +} + +GTEST_DEFINE_bool_( + also_run_disabled_tests, + internal::BoolFromGTestEnv("also_run_disabled_tests", false), + "Run disabled tests too, in addition to the tests normally being run."); + +GTEST_DEFINE_bool_( + break_on_failure, + internal::BoolFromGTestEnv("break_on_failure", false), + "True iff a failed assertion should be a debugger break-point."); + +GTEST_DEFINE_bool_( + catch_exceptions, + internal::BoolFromGTestEnv("catch_exceptions", true), + "True iff " GTEST_NAME_ + " should catch exceptions and treat them as test failures."); + +GTEST_DEFINE_string_( + color, + internal::StringFromGTestEnv("color", "auto"), + "Whether to use colors in the output. Valid values: yes, no, " + "and auto. 'auto' means to use colors if the output is " + "being sent to a terminal and the TERM environment variable " + "is set to a terminal type that supports colors."); + +GTEST_DEFINE_string_( + filter, + internal::StringFromGTestEnv("filter", GetDefaultFilter()), + "A colon-separated list of glob (not regex) patterns " + "for filtering the tests to run, optionally followed by a " + "'-' and a : separated list of negative patterns (tests to " + "exclude). A test is run if it matches one of the positive " + "patterns and does not match any of the negative patterns."); + +GTEST_DEFINE_bool_(list_tests, false, + "List all tests without running them."); + +GTEST_DEFINE_string_( + output, + internal::StringFromGTestEnv("output", ""), + "A format (currently must be \"xml\"), optionally followed " + "by a colon and an output file name or directory. A directory " + "is indicated by a trailing pathname separator. " + "Examples: \"xml:filename.xml\", \"xml::directoryname/\". " + "If a directory is specified, output files will be created " + "within that directory, with file-names based on the test " + "executable's name and, if necessary, made unique by adding " + "digits."); + +GTEST_DEFINE_bool_( + print_time, + internal::BoolFromGTestEnv("print_time", true), + "True iff " GTEST_NAME_ + " should display elapsed time in text output."); + +GTEST_DEFINE_int32_( + random_seed, + internal::Int32FromGTestEnv("random_seed", 0), + "Random number seed to use when shuffling test orders. Must be in range " + "[1, 99999], or 0 to use a seed based on the current time."); + +GTEST_DEFINE_int32_( + repeat, + internal::Int32FromGTestEnv("repeat", 1), + "How many times to repeat each test. Specify a negative number " + "for repeating forever. Useful for shaking out flaky tests."); + +GTEST_DEFINE_bool_( + show_internal_stack_frames, false, + "True iff " GTEST_NAME_ " should include internal stack frames when " + "printing test failure stack traces."); + +GTEST_DEFINE_bool_( + shuffle, + internal::BoolFromGTestEnv("shuffle", false), + "True iff " GTEST_NAME_ + " should randomize tests' order on every run."); + +GTEST_DEFINE_int32_( + stack_trace_depth, + internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth), + "The maximum number of stack frames to print when an " + "assertion fails. The valid range is 0 through 100, inclusive."); + +GTEST_DEFINE_string_( + stream_result_to, + internal::StringFromGTestEnv("stream_result_to", ""), + "This flag specifies the host name and the port number on which to stream " + "test results. Example: \"localhost:555\". The flag is effective only on " + "Linux."); + +GTEST_DEFINE_bool_( + throw_on_failure, + internal::BoolFromGTestEnv("throw_on_failure", false), + "When this flag is specified, a failed assertion will throw an exception " + "if exceptions are enabled or exit the program with a non-zero code " + "otherwise."); + +namespace internal { + +// Generates a random number from [0, range), using a Linear +// Congruential Generator (LCG). Crashes if 'range' is 0 or greater +// than kMaxRange. +UInt32 Random::Generate(UInt32 range) { + // These constants are the same as are used in glibc's rand(3). + state_ = (1103515245U*state_ + 12345U) % kMaxRange; + + GTEST_CHECK_(range > 0) + << "Cannot generate a number in the range [0, 0)."; + GTEST_CHECK_(range <= kMaxRange) + << "Generation of a number in [0, " << range << ") was requested, " + << "but this can only generate numbers in [0, " << kMaxRange << ")."; + + // Converting via modulus introduces a bit of downward bias, but + // it's simple, and a linear congruential generator isn't too good + // to begin with. + return state_ % range; +} + +// GTestIsInitialized() returns true iff the user has initialized +// Google Test. Useful for catching the user mistake of not initializing +// Google Test before calling RUN_ALL_TESTS(). +// +// A user must call testing::InitGoogleTest() to initialize Google +// Test. g_init_gtest_count is set to the number of times +// InitGoogleTest() has been called. We don't protect this variable +// under a mutex as it is only accessed in the main thread. +GTEST_API_ int g_init_gtest_count = 0; +static bool GTestIsInitialized() { return g_init_gtest_count != 0; } + +// Iterates over a vector of TestCases, keeping a running sum of the +// results of calling a given int-returning method on each. +// Returns the sum. +static int SumOverTestCaseList(const std::vector& case_list, + int (TestCase::*method)() const) { + int sum = 0; + for (size_t i = 0; i < case_list.size(); i++) { + sum += (case_list[i]->*method)(); + } + return sum; +} + +// Returns true iff the test case passed. +static bool TestCasePassed(const TestCase* test_case) { + return test_case->should_run() && test_case->Passed(); +} + +// Returns true iff the test case failed. +static bool TestCaseFailed(const TestCase* test_case) { + return test_case->should_run() && test_case->Failed(); +} + +// Returns true iff test_case contains at least one test that should +// run. +static bool ShouldRunTestCase(const TestCase* test_case) { + return test_case->should_run(); +} + +// AssertHelper constructor. +AssertHelper::AssertHelper(TestPartResult::Type type, + const char* file, + int line, + const char* message) + : data_(new AssertHelperData(type, file, line, message)) { +} + +AssertHelper::~AssertHelper() { + delete data_; +} + +// Message assignment, for assertion streaming support. +void AssertHelper::operator=(const Message& message) const { + UnitTest::GetInstance()-> + AddTestPartResult(data_->type, data_->file, data_->line, + AppendUserMessage(data_->message, message), + UnitTest::GetInstance()->impl() + ->CurrentOsStackTraceExceptTop(1) + // Skips the stack frame for this function itself. + ); // NOLINT +} + +// Mutex for linked pointers. +GTEST_API_ GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex); + +// Application pathname gotten in InitGoogleTest. +std::string g_executable_path; + +// Returns the current application's name, removing directory path if that +// is present. +FilePath GetCurrentExecutableName() { + FilePath result; + +#if GTEST_OS_WINDOWS + result.Set(FilePath(g_executable_path).RemoveExtension("exe")); +#else + result.Set(FilePath(g_executable_path)); +#endif // GTEST_OS_WINDOWS + + return result.RemoveDirectoryName(); +} + +// Functions for processing the gtest_output flag. + +// Returns the output format, or "" for normal printed output. +std::string UnitTestOptions::GetOutputFormat() { + const char* const gtest_output_flag = GTEST_FLAG(output).c_str(); + if (gtest_output_flag == NULL) return std::string(""); + + const char* const colon = strchr(gtest_output_flag, ':'); + return (colon == NULL) ? + std::string(gtest_output_flag) : + std::string(gtest_output_flag, colon - gtest_output_flag); +} + +// Returns the name of the requested output file, or the default if none +// was explicitly specified. +std::string UnitTestOptions::GetAbsolutePathToOutputFile() { + const char* const gtest_output_flag = GTEST_FLAG(output).c_str(); + if (gtest_output_flag == NULL) + return ""; + + const char* const colon = strchr(gtest_output_flag, ':'); + if (colon == NULL) + return internal::FilePath::ConcatPaths( + internal::FilePath( + UnitTest::GetInstance()->original_working_dir()), + internal::FilePath(kDefaultOutputFile)).string(); + + internal::FilePath output_name(colon + 1); + if (!output_name.IsAbsolutePath()) + // TODO(wan@google.com): on Windows \some\path is not an absolute + // path (as its meaning depends on the current drive), yet the + // following logic for turning it into an absolute path is wrong. + // Fix it. + output_name = internal::FilePath::ConcatPaths( + internal::FilePath(UnitTest::GetInstance()->original_working_dir()), + internal::FilePath(colon + 1)); + + if (!output_name.IsDirectory()) + return output_name.string(); + + internal::FilePath result(internal::FilePath::GenerateUniqueFileName( + output_name, internal::GetCurrentExecutableName(), + GetOutputFormat().c_str())); + return result.string(); +} + +// Returns true iff the wildcard pattern matches the string. The +// first ':' or '\0' character in pattern marks the end of it. +// +// This recursive algorithm isn't very efficient, but is clear and +// works well enough for matching test names, which are short. +bool UnitTestOptions::PatternMatchesString(const char *pattern, + const char *str) { + switch (*pattern) { + case '\0': + case ':': // Either ':' or '\0' marks the end of the pattern. + return *str == '\0'; + case '?': // Matches any single character. + return *str != '\0' && PatternMatchesString(pattern + 1, str + 1); + case '*': // Matches any string (possibly empty) of characters. + return (*str != '\0' && PatternMatchesString(pattern, str + 1)) || + PatternMatchesString(pattern + 1, str); + default: // Non-special character. Matches itself. + return *pattern == *str && + PatternMatchesString(pattern + 1, str + 1); + } +} + +bool UnitTestOptions::MatchesFilter( + const std::string& name, const char* filter) { + const char *cur_pattern = filter; + for (;;) { + if (PatternMatchesString(cur_pattern, name.c_str())) { + return true; + } + + // Finds the next pattern in the filter. + cur_pattern = strchr(cur_pattern, ':'); + + // Returns if no more pattern can be found. + if (cur_pattern == NULL) { + return false; + } + + // Skips the pattern separater (the ':' character). + cur_pattern++; + } +} + +// Returns true iff the user-specified filter matches the test case +// name and the test name. +bool UnitTestOptions::FilterMatchesTest(const std::string &test_case_name, + const std::string &test_name) { + const std::string& full_name = test_case_name + "." + test_name.c_str(); + + // Split --gtest_filter at '-', if there is one, to separate into + // positive filter and negative filter portions + const char* const p = GTEST_FLAG(filter).c_str(); + const char* const dash = strchr(p, '-'); + std::string positive; + std::string negative; + if (dash == NULL) { + positive = GTEST_FLAG(filter).c_str(); // Whole string is a positive filter + negative = ""; + } else { + positive = std::string(p, dash); // Everything up to the dash + negative = std::string(dash + 1); // Everything after the dash + if (positive.empty()) { + // Treat '-test1' as the same as '*-test1' + positive = kUniversalFilter; + } + } + + // A filter is a colon-separated list of patterns. It matches a + // test if any pattern in it matches the test. + return (MatchesFilter(full_name, positive.c_str()) && + !MatchesFilter(full_name, negative.c_str())); +} + +#if GTEST_HAS_SEH +// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the +// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise. +// This function is useful as an __except condition. +int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) { + // Google Test should handle a SEH exception if: + // 1. the user wants it to, AND + // 2. this is not a breakpoint exception, AND + // 3. this is not a C++ exception (VC++ implements them via SEH, + // apparently). + // + // SEH exception code for C++ exceptions. + // (see http://support.microsoft.com/kb/185294 for more information). + const DWORD kCxxExceptionCode = 0xe06d7363; + + bool should_handle = true; + + if (!GTEST_FLAG(catch_exceptions)) + should_handle = false; + else if (exception_code == EXCEPTION_BREAKPOINT) + should_handle = false; + else if (exception_code == kCxxExceptionCode) + should_handle = false; + + return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH; +} +#endif // GTEST_HAS_SEH + +} // namespace internal + +// The c'tor sets this object as the test part result reporter used by +// Google Test. The 'result' parameter specifies where to report the +// results. Intercepts only failures from the current thread. +ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter( + TestPartResultArray* result) + : intercept_mode_(INTERCEPT_ONLY_CURRENT_THREAD), + result_(result) { + Init(); +} + +// The c'tor sets this object as the test part result reporter used by +// Google Test. The 'result' parameter specifies where to report the +// results. +ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter( + InterceptMode intercept_mode, TestPartResultArray* result) + : intercept_mode_(intercept_mode), + result_(result) { + Init(); +} + +void ScopedFakeTestPartResultReporter::Init() { + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + if (intercept_mode_ == INTERCEPT_ALL_THREADS) { + old_reporter_ = impl->GetGlobalTestPartResultReporter(); + impl->SetGlobalTestPartResultReporter(this); + } else { + old_reporter_ = impl->GetTestPartResultReporterForCurrentThread(); + impl->SetTestPartResultReporterForCurrentThread(this); + } +} + +// The d'tor restores the test part result reporter used by Google Test +// before. +ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() { + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + if (intercept_mode_ == INTERCEPT_ALL_THREADS) { + impl->SetGlobalTestPartResultReporter(old_reporter_); + } else { + impl->SetTestPartResultReporterForCurrentThread(old_reporter_); + } +} + +// Increments the test part result count and remembers the result. +// This method is from the TestPartResultReporterInterface interface. +void ScopedFakeTestPartResultReporter::ReportTestPartResult( + const TestPartResult& result) { + result_->Append(result); +} + +namespace internal { + +// Returns the type ID of ::testing::Test. We should always call this +// instead of GetTypeId< ::testing::Test>() to get the type ID of +// testing::Test. This is to work around a suspected linker bug when +// using Google Test as a framework on Mac OS X. The bug causes +// GetTypeId< ::testing::Test>() to return different values depending +// on whether the call is from the Google Test framework itself or +// from user test code. GetTestTypeId() is guaranteed to always +// return the same value, as it always calls GetTypeId<>() from the +// gtest.cc, which is within the Google Test framework. +TypeId GetTestTypeId() { + return GetTypeId(); +} + +// The value of GetTestTypeId() as seen from within the Google Test +// library. This is solely for testing GetTestTypeId(). +extern const TypeId kTestTypeIdInGoogleTest = GetTestTypeId(); + +// This predicate-formatter checks that 'results' contains a test part +// failure of the given type and that the failure message contains the +// given substring. +AssertionResult HasOneFailure(const char* /* results_expr */, + const char* /* type_expr */, + const char* /* substr_expr */, + const TestPartResultArray& results, + TestPartResult::Type type, + const string& substr) { + const std::string expected(type == TestPartResult::kFatalFailure ? + "1 fatal failure" : + "1 non-fatal failure"); + Message msg; + if (results.size() != 1) { + msg << "Expected: " << expected << "\n" + << " Actual: " << results.size() << " failures"; + for (int i = 0; i < results.size(); i++) { + msg << "\n" << results.GetTestPartResult(i); + } + return AssertionFailure() << msg; + } + + const TestPartResult& r = results.GetTestPartResult(0); + if (r.type() != type) { + return AssertionFailure() << "Expected: " << expected << "\n" + << " Actual:\n" + << r; + } + + if (strstr(r.message(), substr.c_str()) == NULL) { + return AssertionFailure() << "Expected: " << expected << " containing \"" + << substr << "\"\n" + << " Actual:\n" + << r; + } + + return AssertionSuccess(); +} + +// The constructor of SingleFailureChecker remembers where to look up +// test part results, what type of failure we expect, and what +// substring the failure message should contain. +SingleFailureChecker:: SingleFailureChecker( + const TestPartResultArray* results, + TestPartResult::Type type, + const string& substr) + : results_(results), + type_(type), + substr_(substr) {} + +// The destructor of SingleFailureChecker verifies that the given +// TestPartResultArray contains exactly one failure that has the given +// type and contains the given substring. If that's not the case, a +// non-fatal failure will be generated. +SingleFailureChecker::~SingleFailureChecker() { + EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_); +} + +DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter( + UnitTestImpl* unit_test) : unit_test_(unit_test) {} + +void DefaultGlobalTestPartResultReporter::ReportTestPartResult( + const TestPartResult& result) { + unit_test_->current_test_result()->AddTestPartResult(result); + unit_test_->listeners()->repeater()->OnTestPartResult(result); +} + +DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter( + UnitTestImpl* unit_test) : unit_test_(unit_test) {} + +void DefaultPerThreadTestPartResultReporter::ReportTestPartResult( + const TestPartResult& result) { + unit_test_->GetGlobalTestPartResultReporter()->ReportTestPartResult(result); +} + +// Returns the global test part result reporter. +TestPartResultReporterInterface* +UnitTestImpl::GetGlobalTestPartResultReporter() { + internal::MutexLock lock(&global_test_part_result_reporter_mutex_); + return global_test_part_result_repoter_; +} + +// Sets the global test part result reporter. +void UnitTestImpl::SetGlobalTestPartResultReporter( + TestPartResultReporterInterface* reporter) { + internal::MutexLock lock(&global_test_part_result_reporter_mutex_); + global_test_part_result_repoter_ = reporter; +} + +// Returns the test part result reporter for the current thread. +TestPartResultReporterInterface* +UnitTestImpl::GetTestPartResultReporterForCurrentThread() { + return per_thread_test_part_result_reporter_.get(); +} + +// Sets the test part result reporter for the current thread. +void UnitTestImpl::SetTestPartResultReporterForCurrentThread( + TestPartResultReporterInterface* reporter) { + per_thread_test_part_result_reporter_.set(reporter); +} + +// Gets the number of successful test cases. +int UnitTestImpl::successful_test_case_count() const { + return CountIf(test_cases_, TestCasePassed); +} + +// Gets the number of failed test cases. +int UnitTestImpl::failed_test_case_count() const { + return CountIf(test_cases_, TestCaseFailed); +} + +// Gets the number of all test cases. +int UnitTestImpl::total_test_case_count() const { + return static_cast(test_cases_.size()); +} + +// Gets the number of all test cases that contain at least one test +// that should run. +int UnitTestImpl::test_case_to_run_count() const { + return CountIf(test_cases_, ShouldRunTestCase); +} + +// Gets the number of successful tests. +int UnitTestImpl::successful_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::successful_test_count); +} + +// Gets the number of failed tests. +int UnitTestImpl::failed_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::failed_test_count); +} + +// Gets the number of disabled tests that will be reported in the XML report. +int UnitTestImpl::reportable_disabled_test_count() const { + return SumOverTestCaseList(test_cases_, + &TestCase::reportable_disabled_test_count); +} + +// Gets the number of disabled tests. +int UnitTestImpl::disabled_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::disabled_test_count); +} + +// Gets the number of tests to be printed in the XML report. +int UnitTestImpl::reportable_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::reportable_test_count); +} + +// Gets the number of all tests. +int UnitTestImpl::total_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::total_test_count); +} + +// Gets the number of tests that should run. +int UnitTestImpl::test_to_run_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::test_to_run_count); +} + +// Returns the current OS stack trace as an std::string. +// +// The maximum number of stack frames to be included is specified by +// the gtest_stack_trace_depth flag. The skip_count parameter +// specifies the number of top frames to be skipped, which doesn't +// count against the number of frames to be included. +// +// For example, if Foo() calls Bar(), which in turn calls +// CurrentOsStackTraceExceptTop(1), Foo() will be included in the +// trace but Bar() and CurrentOsStackTraceExceptTop() won't. +std::string UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) { + (void)skip_count; + return ""; +} + +// Returns the current time in milliseconds. +TimeInMillis GetTimeInMillis() { +#if GTEST_OS_WINDOWS_MOBILE || defined(__BORLANDC__) + // Difference between 1970-01-01 and 1601-01-01 in milliseconds. + // http://analogous.blogspot.com/2005/04/epoch.html + const TimeInMillis kJavaEpochToWinFileTimeDelta = + static_cast(116444736UL) * 100000UL; + const DWORD kTenthMicrosInMilliSecond = 10000; + + SYSTEMTIME now_systime; + FILETIME now_filetime; + ULARGE_INTEGER now_int64; + // TODO(kenton@google.com): Shouldn't this just use + // GetSystemTimeAsFileTime()? + GetSystemTime(&now_systime); + if (SystemTimeToFileTime(&now_systime, &now_filetime)) { + now_int64.LowPart = now_filetime.dwLowDateTime; + now_int64.HighPart = now_filetime.dwHighDateTime; + now_int64.QuadPart = (now_int64.QuadPart / kTenthMicrosInMilliSecond) - + kJavaEpochToWinFileTimeDelta; + return now_int64.QuadPart; + } + return 0; +#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_ + __timeb64 now; + +# ifdef _MSC_VER + + // MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996 + // (deprecated function) there. + // TODO(kenton@google.com): Use GetTickCount()? Or use + // SystemTimeToFileTime() +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4996) // Temporarily disables warning 4996. + _ftime64(&now); +# pragma warning(pop) // Restores the warning state. +# else + + _ftime64(&now); + +# endif // _MSC_VER + + return static_cast(now.time) * 1000 + now.millitm; +#elif GTEST_HAS_GETTIMEOFDAY_ + struct timeval now; + gettimeofday(&now, NULL); + return static_cast(now.tv_sec) * 1000 + now.tv_usec / 1000; +#else +# error "Don't know how to get the current time on your system." +#endif +} + +// Utilities + +// class String. + +#if GTEST_OS_WINDOWS_MOBILE +// Creates a UTF-16 wide string from the given ANSI string, allocating +// memory using new. The caller is responsible for deleting the return +// value using delete[]. Returns the wide string, or NULL if the +// input is NULL. +LPCWSTR String::AnsiToUtf16(const char* ansi) { + if (!ansi) return NULL; + const int length = strlen(ansi); + const int unicode_length = + MultiByteToWideChar(CP_ACP, 0, ansi, length, + NULL, 0); + WCHAR* unicode = new WCHAR[unicode_length + 1]; + MultiByteToWideChar(CP_ACP, 0, ansi, length, + unicode, unicode_length); + unicode[unicode_length] = 0; + return unicode; +} + +// Creates an ANSI string from the given wide string, allocating +// memory using new. The caller is responsible for deleting the return +// value using delete[]. Returns the ANSI string, or NULL if the +// input is NULL. +const char* String::Utf16ToAnsi(LPCWSTR utf16_str) { + if (!utf16_str) return NULL; + const int ansi_length = + WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, + NULL, 0, NULL, NULL); + char* ansi = new char[ansi_length + 1]; + WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, + ansi, ansi_length, NULL, NULL); + ansi[ansi_length] = 0; + return ansi; +} + +#endif // GTEST_OS_WINDOWS_MOBILE + +// Compares two C strings. Returns true iff they have the same content. +// +// Unlike strcmp(), this function can handle NULL argument(s). A NULL +// C string is considered different to any non-NULL C string, +// including the empty string. +bool String::CStringEquals(const char * lhs, const char * rhs) { + if ( lhs == NULL ) return rhs == NULL; + + if ( rhs == NULL ) return false; + + return strcmp(lhs, rhs) == 0; +} + +#if GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING + +// Converts an array of wide chars to a narrow string using the UTF-8 +// encoding, and streams the result to the given Message object. +static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length, + Message* msg) { + for (size_t i = 0; i != length; ) { // NOLINT + if (wstr[i] != L'\0') { + *msg << WideStringToUtf8(wstr + i, static_cast(length - i)); + while (i != length && wstr[i] != L'\0') + i++; + } else { + *msg << '\0'; + i++; + } + } +} + +#endif // GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING + +} // namespace internal + +// Constructs an empty Message. +// We allocate the stringstream separately because otherwise each use of +// ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's +// stack frame leading to huge stack frames in some cases; gcc does not reuse +// the stack space. +Message::Message() : ss_(new ::std::stringstream) { + // By default, we want there to be enough precision when printing + // a double to a Message. + *ss_ << std::setprecision(std::numeric_limits::digits10 + 2); +} + +// These two overloads allow streaming a wide C string to a Message +// using the UTF-8 encoding. +Message& Message::operator <<(const wchar_t* wide_c_str) { + return *this << internal::String::ShowWideCString(wide_c_str); +} +Message& Message::operator <<(wchar_t* wide_c_str) { + return *this << internal::String::ShowWideCString(wide_c_str); +} + +#if GTEST_HAS_STD_WSTRING +// Converts the given wide string to a narrow string using the UTF-8 +// encoding, and streams the result to this Message object. +Message& Message::operator <<(const ::std::wstring& wstr) { + internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this); + return *this; +} +#endif // GTEST_HAS_STD_WSTRING + +#if GTEST_HAS_GLOBAL_WSTRING +// Converts the given wide string to a narrow string using the UTF-8 +// encoding, and streams the result to this Message object. +Message& Message::operator <<(const ::wstring& wstr) { + internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this); + return *this; +} +#endif // GTEST_HAS_GLOBAL_WSTRING + +// Gets the text streamed to this object so far as an std::string. +// Each '\0' character in the buffer is replaced with "\\0". +std::string Message::GetString() const { + return internal::StringStreamToString(ss_.get()); +} + +// AssertionResult constructors. +// Used in EXPECT_TRUE/FALSE(assertion_result). +AssertionResult::AssertionResult(const AssertionResult& other) + : success_(other.success_), + message_(other.message_.get() != NULL ? + new ::std::string(*other.message_) : + static_cast< ::std::string*>(NULL)) { +} + +// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. +AssertionResult AssertionResult::operator!() const { + AssertionResult negation(!success_); + if (message_.get() != NULL) + negation << *message_; + return negation; +} + +// Makes a successful assertion result. +AssertionResult AssertionSuccess() { + return AssertionResult(true); +} + +// Makes a failed assertion result. +AssertionResult AssertionFailure() { + return AssertionResult(false); +} + +// Makes a failed assertion result with the given failure message. +// Deprecated; use AssertionFailure() << message. +AssertionResult AssertionFailure(const Message& message) { + return AssertionFailure() << message; +} + +namespace internal { + +// Constructs and returns the message for an equality assertion +// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure. +// +// The first four parameters are the expressions used in the assertion +// and their values, as strings. For example, for ASSERT_EQ(foo, bar) +// where foo is 5 and bar is 6, we have: +// +// expected_expression: "foo" +// actual_expression: "bar" +// expected_value: "5" +// actual_value: "6" +// +// The ignoring_case parameter is true iff the assertion is a +// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will +// be inserted into the message. +AssertionResult EqFailure(const char* expected_expression, + const char* actual_expression, + const std::string& expected_value, + const std::string& actual_value, + bool ignoring_case) { + Message msg; + msg << "Value of: " << actual_expression; + if (actual_value != actual_expression) { + msg << "\n Actual: " << actual_value; + } + + msg << "\nExpected: " << expected_expression; + if (ignoring_case) { + msg << " (ignoring case)"; + } + if (expected_value != expected_expression) { + msg << "\nWhich is: " << expected_value; + } + + return AssertionFailure() << msg; +} + +// Constructs a failure message for Boolean assertions such as EXPECT_TRUE. +std::string GetBoolAssertionFailureMessage( + const AssertionResult& assertion_result, + const char* expression_text, + const char* actual_predicate_value, + const char* expected_predicate_value) { + const char* actual_message = assertion_result.message(); + Message msg; + msg << "Value of: " << expression_text + << "\n Actual: " << actual_predicate_value; + if (actual_message[0] != '\0') + msg << " (" << actual_message << ")"; + msg << "\nExpected: " << expected_predicate_value; + return msg.GetString(); +} + +// Helper function for implementing ASSERT_NEAR. +AssertionResult DoubleNearPredFormat(const char* expr1, + const char* expr2, + const char* abs_error_expr, + double val1, + double val2, + double abs_error) { + const double diff = fabs(val1 - val2); + if (diff <= abs_error) return AssertionSuccess(); + + // TODO(wan): do not print the value of an expression if it's + // already a literal. + return AssertionFailure() + << "The difference between " << expr1 << " and " << expr2 + << " is " << diff << ", which exceeds " << abs_error_expr << ", where\n" + << expr1 << " evaluates to " << val1 << ",\n" + << expr2 << " evaluates to " << val2 << ", and\n" + << abs_error_expr << " evaluates to " << abs_error << "."; +} + + +// Helper template for implementing FloatLE() and DoubleLE(). +template +AssertionResult FloatingPointLE(const char* expr1, + const char* expr2, + RawType val1, + RawType val2) { + // Returns success if val1 is less than val2, + if (val1 < val2) { + return AssertionSuccess(); + } + + // or if val1 is almost equal to val2. + const FloatingPoint lhs(val1), rhs(val2); + if (lhs.AlmostEquals(rhs)) { + return AssertionSuccess(); + } + + // Note that the above two checks will both fail if either val1 or + // val2 is NaN, as the IEEE floating-point standard requires that + // any predicate involving a NaN must return false. + + ::std::stringstream val1_ss; + val1_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << val1; + + ::std::stringstream val2_ss; + val2_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << val2; + + return AssertionFailure() + << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n" + << " Actual: " << StringStreamToString(&val1_ss) << " vs " + << StringStreamToString(&val2_ss); +} + +} // namespace internal + +// Asserts that val1 is less than, or almost equal to, val2. Fails +// otherwise. In particular, it fails if either val1 or val2 is NaN. +AssertionResult FloatLE(const char* expr1, const char* expr2, + float val1, float val2) { + return internal::FloatingPointLE(expr1, expr2, val1, val2); +} + +// Asserts that val1 is less than, or almost equal to, val2. Fails +// otherwise. In particular, it fails if either val1 or val2 is NaN. +AssertionResult DoubleLE(const char* expr1, const char* expr2, + double val1, double val2) { + return internal::FloatingPointLE(expr1, expr2, val1, val2); +} + +namespace internal { + +// The helper function for {ASSERT|EXPECT}_EQ with int or enum +// arguments. +AssertionResult CmpHelperEQ(const char* expected_expression, + const char* actual_expression, + BiggestInt expected, + BiggestInt actual) { + if (expected == actual) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + FormatForComparisonFailureMessage(expected, actual), + FormatForComparisonFailureMessage(actual, expected), + false); +} + +// A macro for implementing the helper functions needed to implement +// ASSERT_?? and EXPECT_?? with integer or enum arguments. It is here +// just to avoid copy-and-paste of similar code. +#define GTEST_IMPL_CMP_HELPER_(op_name, op)\ +AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ + BiggestInt val1, BiggestInt val2) {\ + if (val1 op val2) {\ + return AssertionSuccess();\ + } else {\ + return AssertionFailure() \ + << "Expected: (" << expr1 << ") " #op " (" << expr2\ + << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\ + << " vs " << FormatForComparisonFailureMessage(val2, val1);\ + }\ +} + +// Implements the helper function for {ASSERT|EXPECT}_NE with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(NE, !=) +// Implements the helper function for {ASSERT|EXPECT}_LE with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(LE, <=) +// Implements the helper function for {ASSERT|EXPECT}_LT with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(LT, < ) +// Implements the helper function for {ASSERT|EXPECT}_GE with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(GE, >=) +// Implements the helper function for {ASSERT|EXPECT}_GT with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(GT, > ) + +#undef GTEST_IMPL_CMP_HELPER_ + +// The helper function for {ASSERT|EXPECT}_STREQ. +AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual) { + if (String::CStringEquals(expected, actual)) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + PrintToString(expected), + PrintToString(actual), + false); +} + +// The helper function for {ASSERT|EXPECT}_STRCASEEQ. +AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual) { + if (String::CaseInsensitiveCStringEquals(expected, actual)) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + PrintToString(expected), + PrintToString(actual), + true); +} + +// The helper function for {ASSERT|EXPECT}_STRNE. +AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2) { + if (!String::CStringEquals(s1, s2)) { + return AssertionSuccess(); + } else { + return AssertionFailure() << "Expected: (" << s1_expression << ") != (" + << s2_expression << "), actual: \"" + << s1 << "\" vs \"" << s2 << "\""; + } +} + +// The helper function for {ASSERT|EXPECT}_STRCASENE. +AssertionResult CmpHelperSTRCASENE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2) { + if (!String::CaseInsensitiveCStringEquals(s1, s2)) { + return AssertionSuccess(); + } else { + return AssertionFailure() + << "Expected: (" << s1_expression << ") != (" + << s2_expression << ") (ignoring case), actual: \"" + << s1 << "\" vs \"" << s2 << "\""; + } +} + +} // namespace internal + +namespace { + +// Helper functions for implementing IsSubString() and IsNotSubstring(). + +// This group of overloaded functions return true iff needle is a +// substring of haystack. NULL is considered a substring of itself +// only. + +bool IsSubstringPred(const char* needle, const char* haystack) { + if (needle == NULL || haystack == NULL) + return needle == haystack; + + return strstr(haystack, needle) != NULL; +} + +bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) { + if (needle == NULL || haystack == NULL) + return needle == haystack; + + return wcsstr(haystack, needle) != NULL; +} + +// StringType here can be either ::std::string or ::std::wstring. +template +bool IsSubstringPred(const StringType& needle, + const StringType& haystack) { + return haystack.find(needle) != StringType::npos; +} + +// This function implements either IsSubstring() or IsNotSubstring(), +// depending on the value of the expected_to_be_substring parameter. +// StringType here can be const char*, const wchar_t*, ::std::string, +// or ::std::wstring. +template +AssertionResult IsSubstringImpl( + bool expected_to_be_substring, + const char* needle_expr, const char* haystack_expr, + const StringType& needle, const StringType& haystack) { + if (IsSubstringPred(needle, haystack) == expected_to_be_substring) + return AssertionSuccess(); + + const bool is_wide_string = sizeof(needle[0]) > 1; + const char* const begin_string_quote = is_wide_string ? "L\"" : "\""; + return AssertionFailure() + << "Value of: " << needle_expr << "\n" + << " Actual: " << begin_string_quote << needle << "\"\n" + << "Expected: " << (expected_to_be_substring ? "" : "not ") + << "a substring of " << haystack_expr << "\n" + << "Which is: " << begin_string_quote << haystack << "\""; +} + +} // namespace + +// IsSubstring() and IsNotSubstring() check whether needle is a +// substring of haystack (NULL is considered a substring of itself +// only), and return an appropriate error message when they fail. + +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} + +#if GTEST_HAS_STD_WSTRING +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} +#endif // GTEST_HAS_STD_WSTRING + +namespace internal { + +#if GTEST_OS_WINDOWS + +namespace { + +// Helper function for IsHRESULT{SuccessFailure} predicates +AssertionResult HRESULTFailureHelper(const char* expr, + const char* expected, + long hr) { // NOLINT +# if GTEST_OS_WINDOWS_MOBILE + + // Windows CE doesn't support FormatMessage. + const char error_text[] = ""; + +# else + + // Looks up the human-readable system message for the HRESULT code + // and since we're not passing any params to FormatMessage, we don't + // want inserts expanded. + const DWORD kFlags = FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS; + const DWORD kBufSize = 4096; + // Gets the system's human readable message string for this HRESULT. + char error_text[kBufSize] = { '\0' }; + DWORD message_length = ::FormatMessageA(kFlags, + 0, // no source, we're asking system + hr, // the error + 0, // no line width restrictions + error_text, // output buffer + kBufSize, // buf size + NULL); // no arguments for inserts + // Trims tailing white space (FormatMessage leaves a trailing CR-LF) + for (; message_length && IsSpace(error_text[message_length - 1]); + --message_length) { + error_text[message_length - 1] = '\0'; + } + +# endif // GTEST_OS_WINDOWS_MOBILE + + const std::string error_hex("0x" + String::FormatHexInt(hr)); + return ::testing::AssertionFailure() + << "Expected: " << expr << " " << expected << ".\n" + << " Actual: " << error_hex << " " << error_text << "\n"; +} + +} // namespace + +AssertionResult IsHRESULTSuccess(const char* expr, long hr) { // NOLINT + if (SUCCEEDED(hr)) { + return AssertionSuccess(); + } + return HRESULTFailureHelper(expr, "succeeds", hr); +} + +AssertionResult IsHRESULTFailure(const char* expr, long hr) { // NOLINT + if (FAILED(hr)) { + return AssertionSuccess(); + } + return HRESULTFailureHelper(expr, "fails", hr); +} + +#endif // GTEST_OS_WINDOWS + +// Utility functions for encoding Unicode text (wide strings) in +// UTF-8. + +// A Unicode code-point can have upto 21 bits, and is encoded in UTF-8 +// like this: +// +// Code-point length Encoding +// 0 - 7 bits 0xxxxxxx +// 8 - 11 bits 110xxxxx 10xxxxxx +// 12 - 16 bits 1110xxxx 10xxxxxx 10xxxxxx +// 17 - 21 bits 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + +// The maximum code-point a one-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint1 = (static_cast(1) << 7) - 1; + +// The maximum code-point a two-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint2 = (static_cast(1) << (5 + 6)) - 1; + +// The maximum code-point a three-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint3 = (static_cast(1) << (4 + 2*6)) - 1; + +// The maximum code-point a four-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint4 = (static_cast(1) << (3 + 3*6)) - 1; + +// Chops off the n lowest bits from a bit pattern. Returns the n +// lowest bits. As a side effect, the original bit pattern will be +// shifted to the right by n bits. +inline UInt32 ChopLowBits(UInt32* bits, int n) { + const UInt32 low_bits = *bits & ((static_cast(1) << n) - 1); + *bits >>= n; + return low_bits; +} + +// Converts a Unicode code point to a narrow string in UTF-8 encoding. +// code_point parameter is of type UInt32 because wchar_t may not be +// wide enough to contain a code point. +// If the code_point is not a valid Unicode code point +// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted +// to "(Invalid Unicode 0xXXXXXXXX)". +std::string CodePointToUtf8(UInt32 code_point) { + if (code_point > kMaxCodePoint4) { + return "(Invalid Unicode 0x" + String::FormatHexInt(code_point) + ")"; + } + + char str[5]; // Big enough for the largest valid code point. + if (code_point <= kMaxCodePoint1) { + str[1] = '\0'; + str[0] = static_cast(code_point); // 0xxxxxxx + } else if (code_point <= kMaxCodePoint2) { + str[2] = '\0'; + str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[0] = static_cast(0xC0 | code_point); // 110xxxxx + } else if (code_point <= kMaxCodePoint3) { + str[3] = '\0'; + str[2] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[0] = static_cast(0xE0 | code_point); // 1110xxxx + } else { // code_point <= kMaxCodePoint4 + str[4] = '\0'; + str[3] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[2] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[0] = static_cast(0xF0 | code_point); // 11110xxx + } + return str; +} + +// The following two functions only make sense if the the system +// uses UTF-16 for wide string encoding. All supported systems +// with 16 bit wchar_t (Windows, Cygwin, Symbian OS) do use UTF-16. + +// Determines if the arguments constitute UTF-16 surrogate pair +// and thus should be combined into a single Unicode code point +// using CreateCodePointFromUtf16SurrogatePair. +inline bool IsUtf16SurrogatePair(wchar_t first, wchar_t second) { + return sizeof(wchar_t) == 2 && + (first & 0xFC00) == 0xD800 && (second & 0xFC00) == 0xDC00; +} + +// Creates a Unicode code point from UTF16 surrogate pair. +inline UInt32 CreateCodePointFromUtf16SurrogatePair(wchar_t first, + wchar_t second) { + const UInt32 mask = (1 << 10) - 1; + return (sizeof(wchar_t) == 2) ? + (((first & mask) << 10) | (second & mask)) + 0x10000 : + // This function should not be called when the condition is + // false, but we provide a sensible default in case it is. + static_cast(first); +} + +// Converts a wide string to a narrow string in UTF-8 encoding. +// The wide string is assumed to have the following encoding: +// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS) +// UTF-32 if sizeof(wchar_t) == 4 (on Linux) +// Parameter str points to a null-terminated wide string. +// Parameter num_chars may additionally limit the number +// of wchar_t characters processed. -1 is used when the entire string +// should be processed. +// If the string contains code points that are not valid Unicode code points +// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output +// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding +// and contains invalid UTF-16 surrogate pairs, values in those pairs +// will be encoded as individual Unicode characters from Basic Normal Plane. +std::string WideStringToUtf8(const wchar_t* str, int num_chars) { + if (num_chars == -1) + num_chars = static_cast(wcslen(str)); + + ::std::stringstream stream; + for (int i = 0; i < num_chars; ++i) { + UInt32 unicode_code_point; + + if (str[i] == L'\0') { + break; + } else if (i + 1 < num_chars && IsUtf16SurrogatePair(str[i], str[i + 1])) { + unicode_code_point = CreateCodePointFromUtf16SurrogatePair(str[i], + str[i + 1]); + i++; + } else { + unicode_code_point = static_cast(str[i]); + } + + stream << CodePointToUtf8(unicode_code_point); + } + return StringStreamToString(&stream); +} + +// Converts a wide C string to an std::string using the UTF-8 encoding. +// NULL will be converted to "(null)". +std::string String::ShowWideCString(const wchar_t * wide_c_str) { + if (wide_c_str == NULL) return "(null)"; + + return internal::WideStringToUtf8(wide_c_str, -1); +} + +// Compares two wide C strings. Returns true iff they have the same +// content. +// +// Unlike wcscmp(), this function can handle NULL argument(s). A NULL +// C string is considered different to any non-NULL C string, +// including the empty string. +bool String::WideCStringEquals(const wchar_t * lhs, const wchar_t * rhs) { + if (lhs == NULL) return rhs == NULL; + + if (rhs == NULL) return false; + + return wcscmp(lhs, rhs) == 0; +} + +// Helper function for *_STREQ on wide strings. +AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const wchar_t* expected, + const wchar_t* actual) { + if (String::WideCStringEquals(expected, actual)) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + PrintToString(expected), + PrintToString(actual), + false); +} + +// Helper function for *_STRNE on wide strings. +AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const wchar_t* s1, + const wchar_t* s2) { + if (!String::WideCStringEquals(s1, s2)) { + return AssertionSuccess(); + } + + return AssertionFailure() << "Expected: (" << s1_expression << ") != (" + << s2_expression << "), actual: " + << PrintToString(s1) + << " vs " << PrintToString(s2); +} + +// Compares two C strings, ignoring case. Returns true iff they have +// the same content. +// +// Unlike strcasecmp(), this function can handle NULL argument(s). A +// NULL C string is considered different to any non-NULL C string, +// including the empty string. +bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) { + if (lhs == NULL) + return rhs == NULL; + if (rhs == NULL) + return false; + return posix::StrCaseCmp(lhs, rhs) == 0; +} + + // Compares two wide C strings, ignoring case. Returns true iff they + // have the same content. + // + // Unlike wcscasecmp(), this function can handle NULL argument(s). + // A NULL C string is considered different to any non-NULL wide C string, + // including the empty string. + // NB: The implementations on different platforms slightly differ. + // On windows, this method uses _wcsicmp which compares according to LC_CTYPE + // environment variable. On GNU platform this method uses wcscasecmp + // which compares according to LC_CTYPE category of the current locale. + // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the + // current locale. +bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs, + const wchar_t* rhs) { + if (lhs == NULL) return rhs == NULL; + + if (rhs == NULL) return false; + +#if GTEST_OS_WINDOWS + return _wcsicmp(lhs, rhs) == 0; +#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID + return wcscasecmp(lhs, rhs) == 0; +#else + // Android, Mac OS X and Cygwin don't define wcscasecmp. + // Other unknown OSes may not define it either. + wint_t left, right; + do { + left = towlower(*lhs++); + right = towlower(*rhs++); + } while (left && left == right); + return left == right; +#endif // OS selector +} + +// Returns true iff str ends with the given suffix, ignoring case. +// Any string is considered to end with an empty suffix. +bool String::EndsWithCaseInsensitive( + const std::string& str, const std::string& suffix) { + const size_t str_len = str.length(); + const size_t suffix_len = suffix.length(); + return (str_len >= suffix_len) && + CaseInsensitiveCStringEquals(str.c_str() + str_len - suffix_len, + suffix.c_str()); +} + +// Formats an int value as "%02d". +std::string String::FormatIntWidth2(int value) { + std::stringstream ss; + ss << std::setfill('0') << std::setw(2) << value; + return ss.str(); +} + +// Formats an int value as "%X". +std::string String::FormatHexInt(int value) { + std::stringstream ss; + ss << std::hex << std::uppercase << value; + return ss.str(); +} + +// Formats a byte as "%02X". +std::string String::FormatByte(unsigned char value) { + std::stringstream ss; + ss << std::setfill('0') << std::setw(2) << std::hex << std::uppercase + << static_cast(value); + return ss.str(); +} + +// Converts the buffer in a stringstream to an std::string, converting NUL +// bytes to "\\0" along the way. +std::string StringStreamToString(::std::stringstream* ss) { + const ::std::string& str = ss->str(); + const char* const start = str.c_str(); + const char* const end = start + str.length(); + + std::string result; + result.reserve(2 * (end - start)); + for (const char* ch = start; ch != end; ++ch) { + if (*ch == '\0') { + result += "\\0"; // Replaces NUL with "\\0"; + } else { + result += *ch; + } + } + + return result; +} + +// Appends the user-supplied message to the Google-Test-generated message. +std::string AppendUserMessage(const std::string& gtest_msg, + const Message& user_msg) { + // Appends the user message if it's non-empty. + const std::string user_msg_string = user_msg.GetString(); + if (user_msg_string.empty()) { + return gtest_msg; + } + + return gtest_msg + "\n" + user_msg_string; +} + +} // namespace internal + +// class TestResult + +// Creates an empty TestResult. +TestResult::TestResult() + : death_test_count_(0), + elapsed_time_(0) { +} + +// D'tor. +TestResult::~TestResult() { +} + +// Returns the i-th test part result among all the results. i can +// range from 0 to total_part_count() - 1. If i is not in that range, +// aborts the program. +const TestPartResult& TestResult::GetTestPartResult(int i) const { + if (i < 0 || i >= total_part_count()) + internal::posix::Abort(); + return test_part_results_.at(i); +} + +// Returns the i-th test property. i can range from 0 to +// test_property_count() - 1. If i is not in that range, aborts the +// program. +const TestProperty& TestResult::GetTestProperty(int i) const { + if (i < 0 || i >= test_property_count()) + internal::posix::Abort(); + return test_properties_.at(i); +} + +// Clears the test part results. +void TestResult::ClearTestPartResults() { + test_part_results_.clear(); +} + +// Adds a test part result to the list. +void TestResult::AddTestPartResult(const TestPartResult& test_part_result) { + test_part_results_.push_back(test_part_result); +} + +// Adds a test property to the list. If a property with the same key as the +// supplied property is already represented, the value of this test_property +// replaces the old value for that key. +void TestResult::RecordProperty(const std::string& xml_element, + const TestProperty& test_property) { + if (!ValidateTestProperty(xml_element, test_property)) { + return; + } + internal::MutexLock lock(&test_properites_mutex_); + const std::vector::iterator property_with_matching_key = + std::find_if(test_properties_.begin(), test_properties_.end(), + internal::TestPropertyKeyIs(test_property.key())); + if (property_with_matching_key == test_properties_.end()) { + test_properties_.push_back(test_property); + return; + } + property_with_matching_key->SetValue(test_property.value()); +} + +// The list of reserved attributes used in the element of XML +// output. +static const char* const kReservedTestSuitesAttributes[] = { + "disabled", + "errors", + "failures", + "name", + "random_seed", + "tests", + "time", + "timestamp" +}; + +// The list of reserved attributes used in the element of XML +// output. +static const char* const kReservedTestSuiteAttributes[] = { + "disabled", + "errors", + "failures", + "name", + "tests", + "time" +}; + +// The list of reserved attributes used in the element of XML output. +static const char* const kReservedTestCaseAttributes[] = { + "classname", + "name", + "status", + "time", + "type_param", + "value_param" +}; + +template +std::vector ArrayAsVector(const char* const (&array)[kSize]) { + return std::vector(array, array + kSize); +} + +static std::vector GetReservedAttributesForElement( + const std::string& xml_element) { + if (xml_element == "testsuites") { + return ArrayAsVector(kReservedTestSuitesAttributes); + } else if (xml_element == "testsuite") { + return ArrayAsVector(kReservedTestSuiteAttributes); + } else if (xml_element == "testcase") { + return ArrayAsVector(kReservedTestCaseAttributes); + } else { + GTEST_CHECK_(false) << "Unrecognized xml_element provided: " << xml_element; + } + // This code is unreachable but some compilers may not realizes that. + return std::vector(); +} + +static std::string FormatWordList(const std::vector& words) { + Message word_list; + for (size_t i = 0; i < words.size(); ++i) { + if (i > 0 && words.size() > 2) { + word_list << ", "; + } + if (i == words.size() - 1) { + word_list << "and "; + } + word_list << "'" << words[i] << "'"; + } + return word_list.GetString(); +} + +bool ValidateTestPropertyName(const std::string& property_name, + const std::vector& reserved_names) { + if (std::find(reserved_names.begin(), reserved_names.end(), property_name) != + reserved_names.end()) { + ADD_FAILURE() << "Reserved key used in RecordProperty(): " << property_name + << " (" << FormatWordList(reserved_names) + << " are reserved by " << GTEST_NAME_ << ")"; + return false; + } + return true; +} + +// Adds a failure if the key is a reserved attribute of the element named +// xml_element. Returns true if the property is valid. +bool TestResult::ValidateTestProperty(const std::string& xml_element, + const TestProperty& test_property) { + return ValidateTestPropertyName(test_property.key(), + GetReservedAttributesForElement(xml_element)); +} + +// Clears the object. +void TestResult::Clear() { + test_part_results_.clear(); + test_properties_.clear(); + death_test_count_ = 0; + elapsed_time_ = 0; +} + +// Returns true iff the test failed. +bool TestResult::Failed() const { + for (int i = 0; i < total_part_count(); ++i) { + if (GetTestPartResult(i).failed()) + return true; + } + return false; +} + +// Returns true iff the test part fatally failed. +static bool TestPartFatallyFailed(const TestPartResult& result) { + return result.fatally_failed(); +} + +// Returns true iff the test fatally failed. +bool TestResult::HasFatalFailure() const { + return CountIf(test_part_results_, TestPartFatallyFailed) > 0; +} + +// Returns true iff the test part non-fatally failed. +static bool TestPartNonfatallyFailed(const TestPartResult& result) { + return result.nonfatally_failed(); +} + +// Returns true iff the test has a non-fatal failure. +bool TestResult::HasNonfatalFailure() const { + return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0; +} + +// Gets the number of all test parts. This is the sum of the number +// of successful test parts and the number of failed test parts. +int TestResult::total_part_count() const { + return static_cast(test_part_results_.size()); +} + +// Returns the number of the test properties. +int TestResult::test_property_count() const { + return static_cast(test_properties_.size()); +} + +// class Test + +// Creates a Test object. + +// The c'tor saves the values of all Google Test flags. +Test::Test() + : gtest_flag_saver_(new internal::GTestFlagSaver) { +} + +// The d'tor restores the values of all Google Test flags. +Test::~Test() { + delete gtest_flag_saver_; +} + +// Sets up the test fixture. +// +// A sub-class may override this. +void Test::SetUp() { +} + +// Tears down the test fixture. +// +// A sub-class may override this. +void Test::TearDown() { +} + +// Allows user supplied key value pairs to be recorded for later output. +void Test::RecordProperty(const std::string& key, const std::string& value) { + UnitTest::GetInstance()->RecordProperty(key, value); +} + +// Allows user supplied key value pairs to be recorded for later output. +void Test::RecordProperty(const std::string& key, int value) { + Message value_message; + value_message << value; + RecordProperty(key, value_message.GetString().c_str()); +} + +namespace internal { + +void ReportFailureInUnknownLocation(TestPartResult::Type result_type, + const std::string& message) { + // This function is a friend of UnitTest and as such has access to + // AddTestPartResult. + UnitTest::GetInstance()->AddTestPartResult( + result_type, + NULL, // No info about the source file where the exception occurred. + -1, // We have no info on which line caused the exception. + message, + ""); // No stack trace, either. +} + +} // namespace internal + +// Google Test requires all tests in the same test case to use the same test +// fixture class. This function checks if the current test has the +// same fixture class as the first test in the current test case. If +// yes, it returns true; otherwise it generates a Google Test failure and +// returns false. +bool Test::HasSameFixtureClass() { + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + const TestCase* const test_case = impl->current_test_case(); + + // Info about the first test in the current test case. + const TestInfo* const first_test_info = test_case->test_info_list()[0]; + const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_; + const char* const first_test_name = first_test_info->name(); + + // Info about the current test. + const TestInfo* const this_test_info = impl->current_test_info(); + const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_; + const char* const this_test_name = this_test_info->name(); + + if (this_fixture_id != first_fixture_id) { + // Is the first test defined using TEST? + const bool first_is_TEST = first_fixture_id == internal::GetTestTypeId(); + // Is this test defined using TEST? + const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId(); + + if (first_is_TEST || this_is_TEST) { + // The user mixed TEST and TEST_F in this test case - we'll tell + // him/her how to fix it. + + // Gets the name of the TEST and the name of the TEST_F. Note + // that first_is_TEST and this_is_TEST cannot both be true, as + // the fixture IDs are different for the two tests. + const char* const TEST_name = + first_is_TEST ? first_test_name : this_test_name; + const char* const TEST_F_name = + first_is_TEST ? this_test_name : first_test_name; + + ADD_FAILURE() + << "All tests in the same test case must use the same test fixture\n" + << "class, so mixing TEST_F and TEST in the same test case is\n" + << "illegal. In test case " << this_test_info->test_case_name() + << ",\n" + << "test " << TEST_F_name << " is defined using TEST_F but\n" + << "test " << TEST_name << " is defined using TEST. You probably\n" + << "want to change the TEST to TEST_F or move it to another test\n" + << "case."; + } else { + // The user defined two fixture classes with the same name in + // two namespaces - we'll tell him/her how to fix it. + ADD_FAILURE() + << "All tests in the same test case must use the same test fixture\n" + << "class. However, in test case " + << this_test_info->test_case_name() << ",\n" + << "you defined test " << first_test_name + << " and test " << this_test_name << "\n" + << "using two different test fixture classes. This can happen if\n" + << "the two classes are from different namespaces or translation\n" + << "units and have the same name. You should probably rename one\n" + << "of the classes to put the tests into different test cases."; + } + return false; + } + + return true; +} + +#if GTEST_HAS_SEH + +// Adds an "exception thrown" fatal failure to the current test. This +// function returns its result via an output parameter pointer because VC++ +// prohibits creation of objects with destructors on stack in functions +// using __try (see error C2712). +static std::string* FormatSehExceptionMessage(DWORD exception_code, + const char* location) { + Message message; + message << "SEH exception with code 0x" << std::setbase(16) << + exception_code << std::setbase(10) << " thrown in " << location << "."; + + return new std::string(message.GetString()); +} + +#endif // GTEST_HAS_SEH + +namespace internal { + +#if GTEST_HAS_EXCEPTIONS + +// Adds an "exception thrown" fatal failure to the current test. +static std::string FormatCxxExceptionMessage(const char* description, + const char* location) { + Message message; + if (description != NULL) { + message << "C++ exception with description \"" << description << "\""; + } else { + message << "Unknown C++ exception"; + } + message << " thrown in " << location << "."; + + return message.GetString(); +} + +static std::string PrintTestPartResultToString( + const TestPartResult& test_part_result); + +GoogleTestFailureException::GoogleTestFailureException( + const TestPartResult& failure) + : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {} + +#endif // GTEST_HAS_EXCEPTIONS + +// We put these helper functions in the internal namespace as IBM's xlC +// compiler rejects the code if they were declared static. + +// Runs the given method and handles SEH exceptions it throws, when +// SEH is supported; returns the 0-value for type Result in case of an +// SEH exception. (Microsoft compilers cannot handle SEH and C++ +// exceptions in the same function. Therefore, we provide a separate +// wrapper function for handling SEH exceptions.) +template +Result HandleSehExceptionsInMethodIfSupported( + T* object, Result (T::*method)(), const char* location) { +#if GTEST_HAS_SEH + __try { + return (object->*method)(); + } __except (internal::UnitTestOptions::GTestShouldProcessSEH( // NOLINT + GetExceptionCode())) { + // We create the exception message on the heap because VC++ prohibits + // creation of objects with destructors on stack in functions using __try + // (see error C2712). + std::string* exception_message = FormatSehExceptionMessage( + GetExceptionCode(), location); + internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure, + *exception_message); + delete exception_message; + return static_cast(0); + } +#else + (void)location; + return (object->*method)(); +#endif // GTEST_HAS_SEH +} + +// Runs the given method and catches and reports C++ and/or SEH-style +// exceptions, if they are supported; returns the 0-value for type +// Result in case of an SEH exception. +template +Result HandleExceptionsInMethodIfSupported( + T* object, Result (T::*method)(), const char* location) { + // NOTE: The user code can affect the way in which Google Test handles + // exceptions by setting GTEST_FLAG(catch_exceptions), but only before + // RUN_ALL_TESTS() starts. It is technically possible to check the flag + // after the exception is caught and either report or re-throw the + // exception based on the flag's value: + // + // try { + // // Perform the test method. + // } catch (...) { + // if (GTEST_FLAG(catch_exceptions)) + // // Report the exception as failure. + // else + // throw; // Re-throws the original exception. + // } + // + // However, the purpose of this flag is to allow the program to drop into + // the debugger when the exception is thrown. On most platforms, once the + // control enters the catch block, the exception origin information is + // lost and the debugger will stop the program at the point of the + // re-throw in this function -- instead of at the point of the original + // throw statement in the code under test. For this reason, we perform + // the check early, sacrificing the ability to affect Google Test's + // exception handling in the method where the exception is thrown. + if (internal::GetUnitTestImpl()->catch_exceptions()) { +#if GTEST_HAS_EXCEPTIONS + try { + return HandleSehExceptionsInMethodIfSupported(object, method, location); + } catch (const internal::GoogleTestFailureException&) { // NOLINT + // This exception type can only be thrown by a failed Google + // Test assertion with the intention of letting another testing + // framework catch it. Therefore we just re-throw it. + throw; + } catch (const std::exception& e) { // NOLINT + internal::ReportFailureInUnknownLocation( + TestPartResult::kFatalFailure, + FormatCxxExceptionMessage(e.what(), location)); + } catch (...) { // NOLINT + internal::ReportFailureInUnknownLocation( + TestPartResult::kFatalFailure, + FormatCxxExceptionMessage(NULL, location)); + } + return static_cast(0); +#else + return HandleSehExceptionsInMethodIfSupported(object, method, location); +#endif // GTEST_HAS_EXCEPTIONS + } else { + return (object->*method)(); + } +} + +} // namespace internal + +// Runs the test and updates the test result. +void Test::Run() { + if (!HasSameFixtureClass()) return; + + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()"); + // We will run the test only if SetUp() was successful. + if (!HasFatalFailure()) { + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &Test::TestBody, "the test body"); + } + + // However, we want to clean up as much as possible. Hence we will + // always call TearDown(), even if SetUp() or the test body has + // failed. + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &Test::TearDown, "TearDown()"); +} + +// Returns true iff the current test has a fatal failure. +bool Test::HasFatalFailure() { + return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure(); +} + +// Returns true iff the current test has a non-fatal failure. +bool Test::HasNonfatalFailure() { + return internal::GetUnitTestImpl()->current_test_result()-> + HasNonfatalFailure(); +} + +// class TestInfo + +// Constructs a TestInfo object. It assumes ownership of the test factory +// object. +TestInfo::TestInfo(const std::string& a_test_case_name, + const std::string& a_name, + const char* a_type_param, + const char* a_value_param, + internal::TypeId fixture_class_id, + internal::TestFactoryBase* factory) + : test_case_name_(a_test_case_name), + name_(a_name), + type_param_(a_type_param ? new std::string(a_type_param) : NULL), + value_param_(a_value_param ? new std::string(a_value_param) : NULL), + fixture_class_id_(fixture_class_id), + should_run_(false), + is_disabled_(false), + matches_filter_(false), + factory_(factory), + result_() {} + +// Destructs a TestInfo object. +TestInfo::~TestInfo() { delete factory_; } + +namespace internal { + +// Creates a new TestInfo object and registers it with Google Test; +// returns the created object. +// +// Arguments: +// +// test_case_name: name of the test case +// name: name of the test +// type_param: the name of the test's type parameter, or NULL if +// this is not a typed or a type-parameterized test. +// value_param: text representation of the test's value parameter, +// or NULL if this is not a value-parameterized test. +// fixture_class_id: ID of the test fixture class +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +// factory: pointer to the factory that creates a test object. +// The newly created TestInfo instance will assume +// ownership of the factory object. +TestInfo* MakeAndRegisterTestInfo( + const char* test_case_name, + const char* name, + const char* type_param, + const char* value_param, + TypeId fixture_class_id, + SetUpTestCaseFunc set_up_tc, + TearDownTestCaseFunc tear_down_tc, + TestFactoryBase* factory) { + TestInfo* const test_info = + new TestInfo(test_case_name, name, type_param, value_param, + fixture_class_id, factory); + GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info); + return test_info; +} + +#if GTEST_HAS_PARAM_TEST +void ReportInvalidTestCaseType(const char* test_case_name, + const char* file, int line) { + Message errors; + errors + << "Attempted redefinition of test case " << test_case_name << ".\n" + << "All tests in the same test case must use the same test fixture\n" + << "class. However, in test case " << test_case_name << ", you tried\n" + << "to define a test using a fixture class different from the one\n" + << "used earlier. This can happen if the two fixture classes are\n" + << "from different namespaces and have the same name. You should\n" + << "probably rename one of the classes to put the tests into different\n" + << "test cases."; + + fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), + errors.GetString().c_str()); +} +#endif // GTEST_HAS_PARAM_TEST + +} // namespace internal + +namespace { + +// A predicate that checks the test name of a TestInfo against a known +// value. +// +// This is used for implementation of the TestCase class only. We put +// it in the anonymous namespace to prevent polluting the outer +// namespace. +// +// TestNameIs is copyable. +class TestNameIs { + public: + // Constructor. + // + // TestNameIs has NO default constructor. + explicit TestNameIs(const char* name) + : name_(name) {} + + // Returns true iff the test name of test_info matches name_. + bool operator()(const TestInfo * test_info) const { + return test_info && test_info->name() == name_; + } + + private: + std::string name_; +}; + +} // namespace + +namespace internal { + +// This method expands all parameterized tests registered with macros TEST_P +// and INSTANTIATE_TEST_CASE_P into regular tests and registers those. +// This will be done just once during the program runtime. +void UnitTestImpl::RegisterParameterizedTests() { +#if GTEST_HAS_PARAM_TEST + if (!parameterized_tests_registered_) { + parameterized_test_registry_.RegisterTests(); + parameterized_tests_registered_ = true; + } +#endif +} + +} // namespace internal + +// Creates the test object, runs it, records its result, and then +// deletes it. +void TestInfo::Run() { + if (!should_run_) return; + + // Tells UnitTest where to store test result. + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + impl->set_current_test_info(this); + + TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); + + // Notifies the unit test event listeners that a test is about to start. + repeater->OnTestStart(*this); + + const TimeInMillis start = internal::GetTimeInMillis(); + + impl->os_stack_trace_getter()->UponLeavingGTest(); + + // Creates the test object. + Test* const test = internal::HandleExceptionsInMethodIfSupported( + factory_, &internal::TestFactoryBase::CreateTest, + "the test fixture's constructor"); + + // Runs the test only if the test object was created and its + // constructor didn't generate a fatal failure. + if ((test != NULL) && !Test::HasFatalFailure()) { + // This doesn't throw as all user code that can throw are wrapped into + // exception handling code. + test->Run(); + } + + // Deletes the test object. + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + test, &Test::DeleteSelf_, "the test fixture's destructor"); + + result_.set_elapsed_time(internal::GetTimeInMillis() - start); + + // Notifies the unit test event listener that a test has just finished. + repeater->OnTestEnd(*this); + + // Tells UnitTest to stop associating assertion results to this + // test. + impl->set_current_test_info(NULL); +} + +// class TestCase + +// Gets the number of successful tests in this test case. +int TestCase::successful_test_count() const { + return CountIf(test_info_list_, TestPassed); +} + +// Gets the number of failed tests in this test case. +int TestCase::failed_test_count() const { + return CountIf(test_info_list_, TestFailed); +} + +// Gets the number of disabled tests that will be reported in the XML report. +int TestCase::reportable_disabled_test_count() const { + return CountIf(test_info_list_, TestReportableDisabled); +} + +// Gets the number of disabled tests in this test case. +int TestCase::disabled_test_count() const { + return CountIf(test_info_list_, TestDisabled); +} + +// Gets the number of tests to be printed in the XML report. +int TestCase::reportable_test_count() const { + return CountIf(test_info_list_, TestReportable); +} + +// Get the number of tests in this test case that should run. +int TestCase::test_to_run_count() const { + return CountIf(test_info_list_, ShouldRunTest); +} + +// Gets the number of all tests. +int TestCase::total_test_count() const { + return static_cast(test_info_list_.size()); +} + +// Creates a TestCase with the given name. +// +// Arguments: +// +// name: name of the test case +// a_type_param: the name of the test case's type parameter, or NULL if +// this is not a typed or a type-parameterized test case. +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +TestCase::TestCase(const char* a_name, const char* a_type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc) + : name_(a_name), + type_param_(a_type_param ? new std::string(a_type_param) : NULL), + set_up_tc_(set_up_tc), + tear_down_tc_(tear_down_tc), + should_run_(false), + elapsed_time_(0) { +} + +// Destructor of TestCase. +TestCase::~TestCase() { + // Deletes every Test in the collection. + ForEach(test_info_list_, internal::Delete); +} + +// Returns the i-th test among all the tests. i can range from 0 to +// total_test_count() - 1. If i is not in that range, returns NULL. +const TestInfo* TestCase::GetTestInfo(int i) const { + const int index = GetElementOr(test_indices_, i, -1); + return index < 0 ? NULL : test_info_list_[index]; +} + +// Returns the i-th test among all the tests. i can range from 0 to +// total_test_count() - 1. If i is not in that range, returns NULL. +TestInfo* TestCase::GetMutableTestInfo(int i) { + const int index = GetElementOr(test_indices_, i, -1); + return index < 0 ? NULL : test_info_list_[index]; +} + +// Adds a test to this test case. Will delete the test upon +// destruction of the TestCase object. +void TestCase::AddTestInfo(TestInfo * test_info) { + test_info_list_.push_back(test_info); + test_indices_.push_back(static_cast(test_indices_.size())); +} + +// Runs every test in this TestCase. +void TestCase::Run() { + if (!should_run_) return; + + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + impl->set_current_test_case(this); + + TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); + + repeater->OnTestCaseStart(*this); + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &TestCase::RunSetUpTestCase, "SetUpTestCase()"); + + const internal::TimeInMillis start = internal::GetTimeInMillis(); + for (int i = 0; i < total_test_count(); i++) { + GetMutableTestInfo(i)->Run(); + } + elapsed_time_ = internal::GetTimeInMillis() - start; + + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &TestCase::RunTearDownTestCase, "TearDownTestCase()"); + + repeater->OnTestCaseEnd(*this); + impl->set_current_test_case(NULL); +} + +// Clears the results of all tests in this test case. +void TestCase::ClearResult() { + ad_hoc_test_result_.Clear(); + ForEach(test_info_list_, TestInfo::ClearTestResult); +} + +// Shuffles the tests in this test case. +void TestCase::ShuffleTests(internal::Random* random) { + Shuffle(random, &test_indices_); +} + +// Restores the test order to before the first shuffle. +void TestCase::UnshuffleTests() { + for (size_t i = 0; i < test_indices_.size(); i++) { + test_indices_[i] = static_cast(i); + } +} + +// Formats a countable noun. Depending on its quantity, either the +// singular form or the plural form is used. e.g. +// +// FormatCountableNoun(1, "formula", "formuli") returns "1 formula". +// FormatCountableNoun(5, "book", "books") returns "5 books". +static std::string FormatCountableNoun(int count, + const char * singular_form, + const char * plural_form) { + return internal::StreamableToString(count) + " " + + (count == 1 ? singular_form : plural_form); +} + +// Formats the count of tests. +static std::string FormatTestCount(int test_count) { + return FormatCountableNoun(test_count, "test", "tests"); +} + +// Formats the count of test cases. +static std::string FormatTestCaseCount(int test_case_count) { + return FormatCountableNoun(test_case_count, "test case", "test cases"); +} + +// Converts a TestPartResult::Type enum to human-friendly string +// representation. Both kNonFatalFailure and kFatalFailure are translated +// to "Failure", as the user usually doesn't care about the difference +// between the two when viewing the test result. +static const char * TestPartResultTypeToString(TestPartResult::Type type) { + switch (type) { + case TestPartResult::kSuccess: + return "Success"; + + case TestPartResult::kNonFatalFailure: + case TestPartResult::kFatalFailure: +#ifdef _MSC_VER + return "error: "; +#else + return "Failure\n"; +#endif + default: + return "Unknown result type"; + } +} + +namespace internal { + +// Prints a TestPartResult to an std::string. +static std::string PrintTestPartResultToString( + const TestPartResult& test_part_result) { + return (Message() + << internal::FormatFileLocation(test_part_result.file_name(), + test_part_result.line_number()) + << " " << TestPartResultTypeToString(test_part_result.type()) + << test_part_result.message()).GetString(); +} + +// Prints a TestPartResult. +static void PrintTestPartResult(const TestPartResult& test_part_result) { + const std::string& result = + PrintTestPartResultToString(test_part_result); + printf("%s\n", result.c_str()); + fflush(stdout); + // If the test program runs in Visual Studio or a debugger, the + // following statements add the test part result message to the Output + // window such that the user can double-click on it to jump to the + // corresponding source code location; otherwise they do nothing. +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + // We don't call OutputDebugString*() on Windows Mobile, as printing + // to stdout is done by OutputDebugString() there already - we don't + // want the same message printed twice. + ::OutputDebugStringA(result.c_str()); + ::OutputDebugStringA("\n"); +#endif +} + +// class PrettyUnitTestResultPrinter + +enum GTestColor { + COLOR_DEFAULT, + COLOR_RED, + COLOR_GREEN, + COLOR_YELLOW +}; + +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + +// Returns the character attribute for the given color. +WORD GetColorAttribute(GTestColor color) { + switch (color) { + case COLOR_RED: return FOREGROUND_RED; + case COLOR_GREEN: return FOREGROUND_GREEN; + case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN; + default: return 0; + } +} + +#else + +// Returns the ANSI color code for the given color. COLOR_DEFAULT is +// an invalid input. +const char* GetAnsiColorCode(GTestColor color) { + switch (color) { + case COLOR_RED: return "1"; + case COLOR_GREEN: return "2"; + case COLOR_YELLOW: return "3"; + default: return NULL; + }; +} + +#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + +// Returns true iff Google Test should use colors in the output. +bool ShouldUseColor(bool stdout_is_tty) { + const char* const gtest_color = GTEST_FLAG(color).c_str(); + + if (String::CaseInsensitiveCStringEquals(gtest_color, "auto")) { +#if GTEST_OS_WINDOWS + // On Windows the TERM variable is usually not set, but the + // console there does support colors. + return stdout_is_tty; +#else + // On non-Windows platforms, we rely on the TERM variable. + const char* const term = posix::GetEnv("TERM"); + const bool term_supports_color = + String::CStringEquals(term, "xterm") || + String::CStringEquals(term, "xterm-color") || + String::CStringEquals(term, "xterm-256color") || + String::CStringEquals(term, "screen") || + String::CStringEquals(term, "screen-256color") || + String::CStringEquals(term, "linux") || + String::CStringEquals(term, "cygwin"); + return stdout_is_tty && term_supports_color; +#endif // GTEST_OS_WINDOWS + } + + return String::CaseInsensitiveCStringEquals(gtest_color, "yes") || + String::CaseInsensitiveCStringEquals(gtest_color, "true") || + String::CaseInsensitiveCStringEquals(gtest_color, "t") || + String::CStringEquals(gtest_color, "1"); + // We take "yes", "true", "t", and "1" as meaning "yes". If the + // value is neither one of these nor "auto", we treat it as "no" to + // be conservative. +} + +// Helpers for printing colored strings to stdout. Note that on Windows, we +// cannot simply emit special characters and have the terminal change colors. +// This routine must actually emit the characters rather than return a string +// that would be colored when printed, as can be done on Linux. +void ColoredPrintf(GTestColor color, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + +#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS || GTEST_OS_IOS + const bool use_color = false; +#else + static const bool in_color_mode = + ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0); + const bool use_color = in_color_mode && (color != COLOR_DEFAULT); +#endif // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS + // The '!= 0' comparison is necessary to satisfy MSVC 7.1. + + if (!use_color) { + vprintf(fmt, args); + va_end(args); + return; + } + +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); + + // Gets the current text color. + CONSOLE_SCREEN_BUFFER_INFO buffer_info; + GetConsoleScreenBufferInfo(stdout_handle, &buffer_info); + const WORD old_color_attrs = buffer_info.wAttributes; + + // We need to flush the stream buffers into the console before each + // SetConsoleTextAttribute call lest it affect the text that is already + // printed but has not yet reached the console. + fflush(stdout); + SetConsoleTextAttribute(stdout_handle, + GetColorAttribute(color) | FOREGROUND_INTENSITY); + vprintf(fmt, args); + + fflush(stdout); + // Restores the text color. + SetConsoleTextAttribute(stdout_handle, old_color_attrs); +#else + printf("\033[0;3%sm", GetAnsiColorCode(color)); + vprintf(fmt, args); + printf("\033[m"); // Resets the terminal to default. +#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + va_end(args); +} + +// Text printed in Google Test's text output and --gunit_list_tests +// output to label the type parameter and value parameter for a test. +static const char kTypeParamLabel[] = "TypeParam"; +static const char kValueParamLabel[] = "GetParam()"; + +void PrintFullTestCommentIfPresent(const TestInfo& test_info) { + const char* const type_param = test_info.type_param(); + const char* const value_param = test_info.value_param(); + + if (type_param != NULL || value_param != NULL) { + printf(", where "); + if (type_param != NULL) { + printf("%s = %s", kTypeParamLabel, type_param); + if (value_param != NULL) + printf(" and "); + } + if (value_param != NULL) { + printf("%s = %s", kValueParamLabel, value_param); + } + } +} + +// This class implements the TestEventListener interface. +// +// Class PrettyUnitTestResultPrinter is copyable. +class PrettyUnitTestResultPrinter : public TestEventListener { + public: + PrettyUnitTestResultPrinter() {} + static void PrintTestName(const char * test_case, const char * test) { + printf("%s.%s", test_case, test); + } + + // The following methods override what's in the TestEventListener class. + virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration); + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test); + virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestCaseStart(const TestCase& test_case); + virtual void OnTestStart(const TestInfo& test_info); + virtual void OnTestPartResult(const TestPartResult& result); + virtual void OnTestEnd(const TestInfo& test_info); + virtual void OnTestCaseEnd(const TestCase& test_case); + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test); + virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} + + private: + static void PrintFailedTests(const UnitTest& unit_test); +}; + + // Fired before each iteration of tests starts. +void PrettyUnitTestResultPrinter::OnTestIterationStart( + const UnitTest& unit_test, int iteration) { + if (GTEST_FLAG(repeat) != 1) + printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration + 1); + + const char* const filter = GTEST_FLAG(filter).c_str(); + + // Prints the filter if it's not *. This reminds the user that some + // tests may be skipped. + if (!String::CStringEquals(filter, kUniversalFilter)) { + ColoredPrintf(COLOR_YELLOW, + "Note: %s filter = %s\n", GTEST_NAME_, filter); + } + + if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) { + const Int32 shard_index = Int32FromEnvOrDie(kTestShardIndex, -1); + ColoredPrintf(COLOR_YELLOW, + "Note: This is test shard %d of %s.\n", + static_cast(shard_index) + 1, + internal::posix::GetEnv(kTestTotalShards)); + } + + if (GTEST_FLAG(shuffle)) { + ColoredPrintf(COLOR_YELLOW, + "Note: Randomizing tests' orders with a seed of %d .\n", + unit_test.random_seed()); + } + + ColoredPrintf(COLOR_GREEN, "[==========] "); + printf("Running %s from %s.\n", + FormatTestCount(unit_test.test_to_run_count()).c_str(), + FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str()); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart( + const UnitTest& /*unit_test*/) { + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("Global test environment set-up.\n"); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) { + const std::string counts = + FormatCountableNoun(test_case.test_to_run_count(), "test", "tests"); + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("%s from %s", counts.c_str(), test_case.name()); + if (test_case.type_param() == NULL) { + printf("\n"); + } else { + printf(", where %s = %s\n", kTypeParamLabel, test_case.type_param()); + } + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) { + ColoredPrintf(COLOR_GREEN, "[ RUN ] "); + PrintTestName(test_info.test_case_name(), test_info.name()); + printf("\n"); + fflush(stdout); +} + +// Called after an assertion failure. +void PrettyUnitTestResultPrinter::OnTestPartResult( + const TestPartResult& result) { + // If the test part succeeded, we don't need to do anything. + if (result.type() == TestPartResult::kSuccess) + return; + + // Print failure message from the assertion (e.g. expected this and got that). + PrintTestPartResult(result); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) { + if (test_info.result()->Passed()) { + ColoredPrintf(COLOR_GREEN, "[ OK ] "); + } else { + ColoredPrintf(COLOR_RED, "[ FAILED ] "); + } + PrintTestName(test_info.test_case_name(), test_info.name()); + if (test_info.result()->Failed()) + PrintFullTestCommentIfPresent(test_info); + + if (GTEST_FLAG(print_time)) { + printf(" (%s ms)\n", internal::StreamableToString( + test_info.result()->elapsed_time()).c_str()); + } else { + printf("\n"); + } + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) { + if (!GTEST_FLAG(print_time)) return; + + const std::string counts = + FormatCountableNoun(test_case.test_to_run_count(), "test", "tests"); + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("%s from %s (%s ms total)\n\n", + counts.c_str(), test_case.name(), + internal::StreamableToString(test_case.elapsed_time()).c_str()); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnEnvironmentsTearDownStart( + const UnitTest& /*unit_test*/) { + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("Global test environment tear-down\n"); + fflush(stdout); +} + +// Internal helper for printing the list of failed tests. +void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) { + const int failed_test_count = unit_test.failed_test_count(); + if (failed_test_count == 0) { + return; + } + + for (int i = 0; i < unit_test.total_test_case_count(); ++i) { + const TestCase& test_case = *unit_test.GetTestCase(i); + if (!test_case.should_run() || (test_case.failed_test_count() == 0)) { + continue; + } + for (int j = 0; j < test_case.total_test_count(); ++j) { + const TestInfo& test_info = *test_case.GetTestInfo(j); + if (!test_info.should_run() || test_info.result()->Passed()) { + continue; + } + ColoredPrintf(COLOR_RED, "[ FAILED ] "); + printf("%s.%s", test_case.name(), test_info.name()); + PrintFullTestCommentIfPresent(test_info); + printf("\n"); + } + } +} + +void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, + int /*iteration*/) { + ColoredPrintf(COLOR_GREEN, "[==========] "); + printf("%s from %s ran.", + FormatTestCount(unit_test.test_to_run_count()).c_str(), + FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str()); + if (GTEST_FLAG(print_time)) { + printf(" (%s ms total)", + internal::StreamableToString(unit_test.elapsed_time()).c_str()); + } + printf("\n"); + ColoredPrintf(COLOR_GREEN, "[ PASSED ] "); + printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str()); + + int num_failures = unit_test.failed_test_count(); + if (!unit_test.Passed()) { + const int failed_test_count = unit_test.failed_test_count(); + ColoredPrintf(COLOR_RED, "[ FAILED ] "); + printf("%s, listed below:\n", FormatTestCount(failed_test_count).c_str()); + PrintFailedTests(unit_test); + printf("\n%2d FAILED %s\n", num_failures, + num_failures == 1 ? "TEST" : "TESTS"); + } + + int num_disabled = unit_test.reportable_disabled_test_count(); + if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) { + if (!num_failures) { + printf("\n"); // Add a spacer if no FAILURE banner is displayed. + } + ColoredPrintf(COLOR_YELLOW, + " YOU HAVE %d DISABLED %s\n\n", + num_disabled, + num_disabled == 1 ? "TEST" : "TESTS"); + } + // Ensure that Google Test output is printed before, e.g., heapchecker output. + fflush(stdout); +} + +// End PrettyUnitTestResultPrinter + +// class TestEventRepeater +// +// This class forwards events to other event listeners. +class TestEventRepeater : public TestEventListener { + public: + TestEventRepeater() : forwarding_enabled_(true) {} + virtual ~TestEventRepeater(); + void Append(TestEventListener *listener); + TestEventListener* Release(TestEventListener* listener); + + // Controls whether events will be forwarded to listeners_. Set to false + // in death test child processes. + bool forwarding_enabled() const { return forwarding_enabled_; } + void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; } + + virtual void OnTestProgramStart(const UnitTest& unit_test); + virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration); + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test); + virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test); + virtual void OnTestCaseStart(const TestCase& test_case); + virtual void OnTestStart(const TestInfo& test_info); + virtual void OnTestPartResult(const TestPartResult& result); + virtual void OnTestEnd(const TestInfo& test_info); + virtual void OnTestCaseEnd(const TestCase& test_case); + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test); + virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test); + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + virtual void OnTestProgramEnd(const UnitTest& unit_test); + + private: + // Controls whether events will be forwarded to listeners_. Set to false + // in death test child processes. + bool forwarding_enabled_; + // The list of listeners that receive events. + std::vector listeners_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventRepeater); +}; + +TestEventRepeater::~TestEventRepeater() { + ForEach(listeners_, Delete); +} + +void TestEventRepeater::Append(TestEventListener *listener) { + listeners_.push_back(listener); +} + +// TODO(vladl@google.com): Factor the search functionality into Vector::Find. +TestEventListener* TestEventRepeater::Release(TestEventListener *listener) { + for (size_t i = 0; i < listeners_.size(); ++i) { + if (listeners_[i] == listener) { + listeners_.erase(listeners_.begin() + i); + return listener; + } + } + + return NULL; +} + +// Since most methods are very similar, use macros to reduce boilerplate. +// This defines a member that forwards the call to all listeners. +#define GTEST_REPEATER_METHOD_(Name, Type) \ +void TestEventRepeater::Name(const Type& parameter) { \ + if (forwarding_enabled_) { \ + for (size_t i = 0; i < listeners_.size(); i++) { \ + listeners_[i]->Name(parameter); \ + } \ + } \ +} +// This defines a member that forwards the call to all listeners in reverse +// order. +#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \ +void TestEventRepeater::Name(const Type& parameter) { \ + if (forwarding_enabled_) { \ + for (int i = static_cast(listeners_.size()) - 1; i >= 0; i--) { \ + listeners_[i]->Name(parameter); \ + } \ + } \ +} + +GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest) +GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest) +GTEST_REPEATER_METHOD_(OnTestCaseStart, TestCase) +GTEST_REPEATER_METHOD_(OnTestStart, TestInfo) +GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult) +GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo) +GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestCase) +GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest) + +#undef GTEST_REPEATER_METHOD_ +#undef GTEST_REVERSE_REPEATER_METHOD_ + +void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test, + int iteration) { + if (forwarding_enabled_) { + for (size_t i = 0; i < listeners_.size(); i++) { + listeners_[i]->OnTestIterationStart(unit_test, iteration); + } + } +} + +void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test, + int iteration) { + if (forwarding_enabled_) { + for (int i = static_cast(listeners_.size()) - 1; i >= 0; i--) { + listeners_[i]->OnTestIterationEnd(unit_test, iteration); + } + } +} + +// End TestEventRepeater + +// This class generates an XML output file. +class XmlUnitTestResultPrinter : public EmptyTestEventListener { + public: + explicit XmlUnitTestResultPrinter(const char* output_file); + + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + + private: + // Is c a whitespace character that is normalized to a space character + // when it appears in an XML attribute value? + static bool IsNormalizableWhitespace(char c) { + return c == 0x9 || c == 0xA || c == 0xD; + } + + // May c appear in a well-formed XML document? + static bool IsValidXmlCharacter(char c) { + return IsNormalizableWhitespace(c) || c >= 0x20; + } + + // Returns an XML-escaped copy of the input string str. If + // is_attribute is true, the text is meant to appear as an attribute + // value, and normalizable whitespace is preserved by replacing it + // with character references. + static std::string EscapeXml(const std::string& str, bool is_attribute); + + // Returns the given string with all characters invalid in XML removed. + static std::string RemoveInvalidXmlCharacters(const std::string& str); + + // Convenience wrapper around EscapeXml when str is an attribute value. + static std::string EscapeXmlAttribute(const std::string& str) { + return EscapeXml(str, true); + } + + // Convenience wrapper around EscapeXml when str is not an attribute value. + static std::string EscapeXmlText(const char* str) { + return EscapeXml(str, false); + } + + // Verifies that the given attribute belongs to the given element and + // streams the attribute as XML. + static void OutputXmlAttribute(std::ostream* stream, + const std::string& element_name, + const std::string& name, + const std::string& value); + + // Streams an XML CDATA section, escaping invalid CDATA sequences as needed. + static void OutputXmlCDataSection(::std::ostream* stream, const char* data); + + // Streams an XML representation of a TestInfo object. + static void OutputXmlTestInfo(::std::ostream* stream, + const char* test_case_name, + const TestInfo& test_info); + + // Prints an XML representation of a TestCase object + static void PrintXmlTestCase(::std::ostream* stream, + const TestCase& test_case); + + // Prints an XML summary of unit_test to output stream out. + static void PrintXmlUnitTest(::std::ostream* stream, + const UnitTest& unit_test); + + // Produces a string representing the test properties in a result as space + // delimited XML attributes based on the property key="value" pairs. + // When the std::string is not empty, it includes a space at the beginning, + // to delimit this attribute from prior attributes. + static std::string TestPropertiesAsXmlAttributes(const TestResult& result); + + // The output file. + const std::string output_file_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter); +}; + +// Creates a new XmlUnitTestResultPrinter. +XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file) + : output_file_(output_file) { + if (output_file_.c_str() == NULL || output_file_.empty()) { + fprintf(stderr, "XML output file may not be null\n"); + fflush(stderr); + exit(EXIT_FAILURE); + } +} + +// Called after the unit test ends. +void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, + int /*iteration*/) { + FILE* xmlout = NULL; + FilePath output_file(output_file_); + FilePath output_dir(output_file.RemoveFileName()); + + if (output_dir.CreateDirectoriesRecursively()) { + xmlout = posix::FOpen(output_file_.c_str(), "w"); + } + if (xmlout == NULL) { + // TODO(wan): report the reason of the failure. + // + // We don't do it for now as: + // + // 1. There is no urgent need for it. + // 2. It's a bit involved to make the errno variable thread-safe on + // all three operating systems (Linux, Windows, and Mac OS). + // 3. To interpret the meaning of errno in a thread-safe way, + // we need the strerror_r() function, which is not available on + // Windows. + fprintf(stderr, + "Unable to open file \"%s\"\n", + output_file_.c_str()); + fflush(stderr); + exit(EXIT_FAILURE); + } + std::stringstream stream; + PrintXmlUnitTest(&stream, unit_test); + fprintf(xmlout, "%s", StringStreamToString(&stream).c_str()); + fclose(xmlout); +} + +// Returns an XML-escaped copy of the input string str. If is_attribute +// is true, the text is meant to appear as an attribute value, and +// normalizable whitespace is preserved by replacing it with character +// references. +// +// Invalid XML characters in str, if any, are stripped from the output. +// It is expected that most, if not all, of the text processed by this +// module will consist of ordinary English text. +// If this module is ever modified to produce version 1.1 XML output, +// most invalid characters can be retained using character references. +// TODO(wan): It might be nice to have a minimally invasive, human-readable +// escaping scheme for invalid characters, rather than dropping them. +std::string XmlUnitTestResultPrinter::EscapeXml( + const std::string& str, bool is_attribute) { + Message m; + + for (size_t i = 0; i < str.size(); ++i) { + const char ch = str[i]; + switch (ch) { + case '<': + m << "<"; + break; + case '>': + m << ">"; + break; + case '&': + m << "&"; + break; + case '\'': + if (is_attribute) + m << "'"; + else + m << '\''; + break; + case '"': + if (is_attribute) + m << """; + else + m << '"'; + break; + default: + if (IsValidXmlCharacter(ch)) { + if (is_attribute && IsNormalizableWhitespace(ch)) + m << "&#x" << String::FormatByte(static_cast(ch)) + << ";"; + else + m << ch; + } + break; + } + } + + return m.GetString(); +} + +// Returns the given string with all characters invalid in XML removed. +// Currently invalid characters are dropped from the string. An +// alternative is to replace them with certain characters such as . or ?. +std::string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters( + const std::string& str) { + std::string output; + output.reserve(str.size()); + for (std::string::const_iterator it = str.begin(); it != str.end(); ++it) + if (IsValidXmlCharacter(*it)) + output.push_back(*it); + + return output; +} + +// The following routines generate an XML representation of a UnitTest +// object. +// +// This is how Google Test concepts map to the DTD: +// +// <-- corresponds to a UnitTest object +// <-- corresponds to a TestCase object +// <-- corresponds to a TestInfo object +// ... +// ... +// ... +// <-- individual assertion failures +// +// +// + +// Formats the given time in milliseconds as seconds. +std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) { + ::std::stringstream ss; + ss << ms/1000.0; + return ss.str(); +} + +// Converts the given epoch time in milliseconds to a date string in the ISO +// 8601 format, without the timezone information. +std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms) { + // Using non-reentrant version as localtime_r is not portable. + time_t seconds = static_cast(ms / 1000); +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4996) // Temporarily disables warning 4996 + // (function or variable may be unsafe). + const struct tm* const time_struct = localtime(&seconds); // NOLINT +# pragma warning(pop) // Restores the warning state again. +#else + const struct tm* const time_struct = localtime(&seconds); // NOLINT +#endif + if (time_struct == NULL) + return ""; // Invalid ms value + + // YYYY-MM-DDThh:mm:ss + return StreamableToString(time_struct->tm_year + 1900) + "-" + + String::FormatIntWidth2(time_struct->tm_mon + 1) + "-" + + String::FormatIntWidth2(time_struct->tm_mday) + "T" + + String::FormatIntWidth2(time_struct->tm_hour) + ":" + + String::FormatIntWidth2(time_struct->tm_min) + ":" + + String::FormatIntWidth2(time_struct->tm_sec); +} + +// Streams an XML CDATA section, escaping invalid CDATA sequences as needed. +void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream, + const char* data) { + const char* segment = data; + *stream << ""); + if (next_segment != NULL) { + stream->write( + segment, static_cast(next_segment - segment)); + *stream << "]]>]]>"); + } else { + *stream << segment; + break; + } + } + *stream << "]]>"; +} + +void XmlUnitTestResultPrinter::OutputXmlAttribute( + std::ostream* stream, + const std::string& element_name, + const std::string& name, + const std::string& value) { + const std::vector& allowed_names = + GetReservedAttributesForElement(element_name); + + GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) != + allowed_names.end()) + << "Attribute " << name << " is not allowed for element <" << element_name + << ">."; + + *stream << " " << name << "=\"" << EscapeXmlAttribute(value) << "\""; +} + +// Prints an XML representation of a TestInfo object. +// TODO(wan): There is also value in printing properties with the plain printer. +void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream, + const char* test_case_name, + const TestInfo& test_info) { + const TestResult& result = *test_info.result(); + const std::string kTestcase = "testcase"; + + *stream << " \n"; + } + const string location = internal::FormatCompilerIndependentFileLocation( + part.file_name(), part.line_number()); + const string summary = location + "\n" + part.summary(); + *stream << " "; + const string detail = location + "\n" + part.message(); + OutputXmlCDataSection(stream, RemoveInvalidXmlCharacters(detail).c_str()); + *stream << "\n"; + } + } + + if (failures == 0) + *stream << " />\n"; + else + *stream << " \n"; +} + +// Prints an XML representation of a TestCase object +void XmlUnitTestResultPrinter::PrintXmlTestCase(std::ostream* stream, + const TestCase& test_case) { + const std::string kTestsuite = "testsuite"; + *stream << " <" << kTestsuite; + OutputXmlAttribute(stream, kTestsuite, "name", test_case.name()); + OutputXmlAttribute(stream, kTestsuite, "tests", + StreamableToString(test_case.reportable_test_count())); + OutputXmlAttribute(stream, kTestsuite, "failures", + StreamableToString(test_case.failed_test_count())); + OutputXmlAttribute( + stream, kTestsuite, "disabled", + StreamableToString(test_case.reportable_disabled_test_count())); + OutputXmlAttribute(stream, kTestsuite, "errors", "0"); + OutputXmlAttribute(stream, kTestsuite, "time", + FormatTimeInMillisAsSeconds(test_case.elapsed_time())); + *stream << TestPropertiesAsXmlAttributes(test_case.ad_hoc_test_result()) + << ">\n"; + + for (int i = 0; i < test_case.total_test_count(); ++i) { + if (test_case.GetTestInfo(i)->is_reportable()) + OutputXmlTestInfo(stream, test_case.name(), *test_case.GetTestInfo(i)); + } + *stream << " \n"; +} + +// Prints an XML summary of unit_test to output stream out. +void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream, + const UnitTest& unit_test) { + const std::string kTestsuites = "testsuites"; + + *stream << "\n"; + *stream << "<" << kTestsuites; + + OutputXmlAttribute(stream, kTestsuites, "tests", + StreamableToString(unit_test.reportable_test_count())); + OutputXmlAttribute(stream, kTestsuites, "failures", + StreamableToString(unit_test.failed_test_count())); + OutputXmlAttribute( + stream, kTestsuites, "disabled", + StreamableToString(unit_test.reportable_disabled_test_count())); + OutputXmlAttribute(stream, kTestsuites, "errors", "0"); + OutputXmlAttribute( + stream, kTestsuites, "timestamp", + FormatEpochTimeInMillisAsIso8601(unit_test.start_timestamp())); + OutputXmlAttribute(stream, kTestsuites, "time", + FormatTimeInMillisAsSeconds(unit_test.elapsed_time())); + + if (GTEST_FLAG(shuffle)) { + OutputXmlAttribute(stream, kTestsuites, "random_seed", + StreamableToString(unit_test.random_seed())); + } + + *stream << TestPropertiesAsXmlAttributes(unit_test.ad_hoc_test_result()); + + OutputXmlAttribute(stream, kTestsuites, "name", "AllTests"); + *stream << ">\n"; + + for (int i = 0; i < unit_test.total_test_case_count(); ++i) { + if (unit_test.GetTestCase(i)->reportable_test_count() > 0) + PrintXmlTestCase(stream, *unit_test.GetTestCase(i)); + } + *stream << "\n"; +} + +// Produces a string representing the test properties in a result as space +// delimited XML attributes based on the property key="value" pairs. +std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes( + const TestResult& result) { + Message attributes; + for (int i = 0; i < result.test_property_count(); ++i) { + const TestProperty& property = result.GetTestProperty(i); + attributes << " " << property.key() << "=" + << "\"" << EscapeXmlAttribute(property.value()) << "\""; + } + return attributes.GetString(); +} + +// End XmlUnitTestResultPrinter + +#if GTEST_CAN_STREAM_RESULTS_ + +// Checks if str contains '=', '&', '%' or '\n' characters. If yes, +// replaces them by "%xx" where xx is their hexadecimal value. For +// example, replaces "=" with "%3D". This algorithm is O(strlen(str)) +// in both time and space -- important as the input str may contain an +// arbitrarily long test failure message and stack trace. +string StreamingListener::UrlEncode(const char* str) { + string result; + result.reserve(strlen(str) + 1); + for (char ch = *str; ch != '\0'; ch = *++str) { + switch (ch) { + case '%': + case '=': + case '&': + case '\n': + result.append("%" + String::FormatByte(static_cast(ch))); + break; + default: + result.push_back(ch); + break; + } + } + return result; +} + +void StreamingListener::SocketWriter::MakeConnection() { + GTEST_CHECK_(sockfd_ == -1) + << "MakeConnection() can't be called when there is already a connection."; + + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; // To allow both IPv4 and IPv6 addresses. + hints.ai_socktype = SOCK_STREAM; + addrinfo* servinfo = NULL; + + // Use the getaddrinfo() to get a linked list of IP addresses for + // the given host name. + const int error_num = getaddrinfo( + host_name_.c_str(), port_num_.c_str(), &hints, &servinfo); + if (error_num != 0) { + GTEST_LOG_(WARNING) << "stream_result_to: getaddrinfo() failed: " + << gai_strerror(error_num); + } + + // Loop through all the results and connect to the first we can. + for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != NULL; + cur_addr = cur_addr->ai_next) { + sockfd_ = socket( + cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol); + if (sockfd_ != -1) { + // Connect the client socket to the server socket. + if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) { + close(sockfd_); + sockfd_ = -1; + } + } + } + + freeaddrinfo(servinfo); // all done with this structure + + if (sockfd_ == -1) { + GTEST_LOG_(WARNING) << "stream_result_to: failed to connect to " + << host_name_ << ":" << port_num_; + } +} + +// End of class Streaming Listener +#endif // GTEST_CAN_STREAM_RESULTS__ + +// Class ScopedTrace + +// Pushes the given source file location and message onto a per-thread +// trace stack maintained by Google Test. +ScopedTrace::ScopedTrace(const char* file, int line, const Message& message) + GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) { + TraceInfo trace; + trace.file = file; + trace.line = line; + trace.message = message.GetString(); + + UnitTest::GetInstance()->PushGTestTrace(trace); +} + +// Pops the info pushed by the c'tor. +ScopedTrace::~ScopedTrace() + GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) { + UnitTest::GetInstance()->PopGTestTrace(); +} + + +// class OsStackTraceGetter + +// Returns the current OS stack trace as an std::string. Parameters: +// +// max_depth - the maximum number of stack frames to be included +// in the trace. +// skip_count - the number of top frames to be skipped; doesn't count +// against max_depth. +// +string OsStackTraceGetter::CurrentStackTrace(int /* max_depth */, + int /* skip_count */) + GTEST_LOCK_EXCLUDED_(mutex_) { + return ""; +} + +void OsStackTraceGetter::UponLeavingGTest() + GTEST_LOCK_EXCLUDED_(mutex_) { +} + +const char* const +OsStackTraceGetter::kElidedFramesMarker = + "... " GTEST_NAME_ " internal frames ..."; + +// A helper class that creates the premature-exit file in its +// constructor and deletes the file in its destructor. +class ScopedPrematureExitFile { + public: + explicit ScopedPrematureExitFile(const char* premature_exit_filepath) + : premature_exit_filepath_(premature_exit_filepath) { + // If a path to the premature-exit file is specified... + if (premature_exit_filepath != NULL && *premature_exit_filepath != '\0') { + // create the file with a single "0" character in it. I/O + // errors are ignored as there's nothing better we can do and we + // don't want to fail the test because of this. + FILE* pfile = posix::FOpen(premature_exit_filepath, "w"); + fwrite("0", 1, 1, pfile); + fclose(pfile); + } + } + + ~ScopedPrematureExitFile() { + if (premature_exit_filepath_ != NULL && *premature_exit_filepath_ != '\0') { + remove(premature_exit_filepath_); + } + } + + private: + const char* const premature_exit_filepath_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedPrematureExitFile); +}; + +} // namespace internal + +// class TestEventListeners + +TestEventListeners::TestEventListeners() + : repeater_(new internal::TestEventRepeater()), + default_result_printer_(NULL), + default_xml_generator_(NULL) { +} + +TestEventListeners::~TestEventListeners() { delete repeater_; } + +// Returns the standard listener responsible for the default console +// output. Can be removed from the listeners list to shut down default +// console output. Note that removing this object from the listener list +// with Release transfers its ownership to the user. +void TestEventListeners::Append(TestEventListener* listener) { + repeater_->Append(listener); +} + +// Removes the given event listener from the list and returns it. It then +// becomes the caller's responsibility to delete the listener. Returns +// NULL if the listener is not found in the list. +TestEventListener* TestEventListeners::Release(TestEventListener* listener) { + if (listener == default_result_printer_) + default_result_printer_ = NULL; + else if (listener == default_xml_generator_) + default_xml_generator_ = NULL; + return repeater_->Release(listener); +} + +// Returns repeater that broadcasts the TestEventListener events to all +// subscribers. +TestEventListener* TestEventListeners::repeater() { return repeater_; } + +// Sets the default_result_printer attribute to the provided listener. +// The listener is also added to the listener list and previous +// default_result_printer is removed from it and deleted. The listener can +// also be NULL in which case it will not be added to the list. Does +// nothing if the previous and the current listener objects are the same. +void TestEventListeners::SetDefaultResultPrinter(TestEventListener* listener) { + if (default_result_printer_ != listener) { + // It is an error to pass this method a listener that is already in the + // list. + delete Release(default_result_printer_); + default_result_printer_ = listener; + if (listener != NULL) + Append(listener); + } +} + +// Sets the default_xml_generator attribute to the provided listener. The +// listener is also added to the listener list and previous +// default_xml_generator is removed from it and deleted. The listener can +// also be NULL in which case it will not be added to the list. Does +// nothing if the previous and the current listener objects are the same. +void TestEventListeners::SetDefaultXmlGenerator(TestEventListener* listener) { + if (default_xml_generator_ != listener) { + // It is an error to pass this method a listener that is already in the + // list. + delete Release(default_xml_generator_); + default_xml_generator_ = listener; + if (listener != NULL) + Append(listener); + } +} + +// Controls whether events will be forwarded by the repeater to the +// listeners in the list. +bool TestEventListeners::EventForwardingEnabled() const { + return repeater_->forwarding_enabled(); +} + +void TestEventListeners::SuppressEventForwarding() { + repeater_->set_forwarding_enabled(false); +} + +// class UnitTest + +// Gets the singleton UnitTest object. The first time this method is +// called, a UnitTest object is constructed and returned. Consecutive +// calls will return the same object. +// +// We don't protect this under mutex_ as a user is not supposed to +// call this before main() starts, from which point on the return +// value will never change. +UnitTest* UnitTest::GetInstance() { + // When compiled with MSVC 7.1 in optimized mode, destroying the + // UnitTest object upon exiting the program messes up the exit code, + // causing successful tests to appear failed. We have to use a + // different implementation in this case to bypass the compiler bug. + // This implementation makes the compiler happy, at the cost of + // leaking the UnitTest object. + + // CodeGear C++Builder insists on a public destructor for the + // default implementation. Use this implementation to keep good OO + // design with private destructor. + +#if (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__) + static UnitTest* const instance = new UnitTest; + return instance; +#else + static UnitTest instance; + return &instance; +#endif // (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__) +} + +// Gets the number of successful test cases. +int UnitTest::successful_test_case_count() const { + return impl()->successful_test_case_count(); +} + +// Gets the number of failed test cases. +int UnitTest::failed_test_case_count() const { + return impl()->failed_test_case_count(); +} + +// Gets the number of all test cases. +int UnitTest::total_test_case_count() const { + return impl()->total_test_case_count(); +} + +// Gets the number of all test cases that contain at least one test +// that should run. +int UnitTest::test_case_to_run_count() const { + return impl()->test_case_to_run_count(); +} + +// Gets the number of successful tests. +int UnitTest::successful_test_count() const { + return impl()->successful_test_count(); +} + +// Gets the number of failed tests. +int UnitTest::failed_test_count() const { return impl()->failed_test_count(); } + +// Gets the number of disabled tests that will be reported in the XML report. +int UnitTest::reportable_disabled_test_count() const { + return impl()->reportable_disabled_test_count(); +} + +// Gets the number of disabled tests. +int UnitTest::disabled_test_count() const { + return impl()->disabled_test_count(); +} + +// Gets the number of tests to be printed in the XML report. +int UnitTest::reportable_test_count() const { + return impl()->reportable_test_count(); +} + +// Gets the number of all tests. +int UnitTest::total_test_count() const { return impl()->total_test_count(); } + +// Gets the number of tests that should run. +int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); } + +// Gets the time of the test program start, in ms from the start of the +// UNIX epoch. +internal::TimeInMillis UnitTest::start_timestamp() const { + return impl()->start_timestamp(); +} + +// Gets the elapsed time, in milliseconds. +internal::TimeInMillis UnitTest::elapsed_time() const { + return impl()->elapsed_time(); +} + +// Returns true iff the unit test passed (i.e. all test cases passed). +bool UnitTest::Passed() const { return impl()->Passed(); } + +// Returns true iff the unit test failed (i.e. some test case failed +// or something outside of all tests failed). +bool UnitTest::Failed() const { return impl()->Failed(); } + +// Gets the i-th test case among all the test cases. i can range from 0 to +// total_test_case_count() - 1. If i is not in that range, returns NULL. +const TestCase* UnitTest::GetTestCase(int i) const { + return impl()->GetTestCase(i); +} + +// Returns the TestResult containing information on test failures and +// properties logged outside of individual test cases. +const TestResult& UnitTest::ad_hoc_test_result() const { + return *impl()->ad_hoc_test_result(); +} + +// Gets the i-th test case among all the test cases. i can range from 0 to +// total_test_case_count() - 1. If i is not in that range, returns NULL. +TestCase* UnitTest::GetMutableTestCase(int i) { + return impl()->GetMutableTestCase(i); +} + +// Returns the list of event listeners that can be used to track events +// inside Google Test. +TestEventListeners& UnitTest::listeners() { + return *impl()->listeners(); +} + +// Registers and returns a global test environment. When a test +// program is run, all global test environments will be set-up in the +// order they were registered. After all tests in the program have +// finished, all global test environments will be torn-down in the +// *reverse* order they were registered. +// +// The UnitTest object takes ownership of the given environment. +// +// We don't protect this under mutex_, as we only support calling it +// from the main thread. +Environment* UnitTest::AddEnvironment(Environment* env) { + if (env == NULL) { + return NULL; + } + + impl_->environments().push_back(env); + return env; +} + +// Adds a TestPartResult to the current TestResult object. All Google Test +// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call +// this to report their results. The user code should use the +// assertion macros instead of calling this directly. +void UnitTest::AddTestPartResult( + TestPartResult::Type result_type, + const char* file_name, + int line_number, + const std::string& message, + const std::string& os_stack_trace) GTEST_LOCK_EXCLUDED_(mutex_) { + Message msg; + msg << message; + + internal::MutexLock lock(&mutex_); + if (impl_->gtest_trace_stack().size() > 0) { + msg << "\n" << GTEST_NAME_ << " trace:"; + + for (int i = static_cast(impl_->gtest_trace_stack().size()); + i > 0; --i) { + const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1]; + msg << "\n" << internal::FormatFileLocation(trace.file, trace.line) + << " " << trace.message; + } + } + + if (os_stack_trace.c_str() != NULL && !os_stack_trace.empty()) { + msg << internal::kStackTraceMarker << os_stack_trace; + } + + const TestPartResult result = + TestPartResult(result_type, file_name, line_number, + msg.GetString().c_str()); + impl_->GetTestPartResultReporterForCurrentThread()-> + ReportTestPartResult(result); + + if (result_type != TestPartResult::kSuccess) { + // gtest_break_on_failure takes precedence over + // gtest_throw_on_failure. This allows a user to set the latter + // in the code (perhaps in order to use Google Test assertions + // with another testing framework) and specify the former on the + // command line for debugging. + if (GTEST_FLAG(break_on_failure)) { +#if GTEST_OS_WINDOWS + // Using DebugBreak on Windows allows gtest to still break into a debugger + // when a failure happens and both the --gtest_break_on_failure and + // the --gtest_catch_exceptions flags are specified. + DebugBreak(); +#else + // Dereference NULL through a volatile pointer to prevent the compiler + // from removing. We use this rather than abort() or __builtin_trap() for + // portability: Symbian doesn't implement abort() well, and some debuggers + // don't correctly trap abort(). + *static_cast(NULL) = 1; +#endif // GTEST_OS_WINDOWS + } else if (GTEST_FLAG(throw_on_failure)) { +#if GTEST_HAS_EXCEPTIONS + throw internal::GoogleTestFailureException(result); +#else + // We cannot call abort() as it generates a pop-up in debug mode + // that cannot be suppressed in VC 7.1 or below. + exit(1); +#endif + } + } +} + +// Adds a TestProperty to the current TestResult object when invoked from +// inside a test, to current TestCase's ad_hoc_test_result_ when invoked +// from SetUpTestCase or TearDownTestCase, or to the global property set +// when invoked elsewhere. If the result already contains a property with +// the same key, the value will be updated. +void UnitTest::RecordProperty(const std::string& key, + const std::string& value) { + impl_->RecordProperty(TestProperty(key, value)); +} + +// Runs all tests in this UnitTest object and prints the result. +// Returns 0 if successful, or 1 otherwise. +// +// We don't protect this under mutex_, as we only support calling it +// from the main thread. +int UnitTest::Run() { + const bool in_death_test_child_process = + internal::GTEST_FLAG(internal_run_death_test).length() > 0; + + // Google Test implements this protocol for catching that a test + // program exits before returning control to Google Test: + // + // 1. Upon start, Google Test creates a file whose absolute path + // is specified by the environment variable + // TEST_PREMATURE_EXIT_FILE. + // 2. When Google Test has finished its work, it deletes the file. + // + // This allows a test runner to set TEST_PREMATURE_EXIT_FILE before + // running a Google-Test-based test program and check the existence + // of the file at the end of the test execution to see if it has + // exited prematurely. + + // If we are in the child process of a death test, don't + // create/delete the premature exit file, as doing so is unnecessary + // and will confuse the parent process. Otherwise, create/delete + // the file upon entering/leaving this function. If the program + // somehow exits before this function has a chance to return, the + // premature-exit file will be left undeleted, causing a test runner + // that understands the premature-exit-file protocol to report the + // test as having failed. + const internal::ScopedPrematureExitFile premature_exit_file( + in_death_test_child_process ? + NULL : internal::posix::GetEnv("TEST_PREMATURE_EXIT_FILE")); + + // Captures the value of GTEST_FLAG(catch_exceptions). This value will be + // used for the duration of the program. + impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions)); + +#if GTEST_HAS_SEH + // Either the user wants Google Test to catch exceptions thrown by the + // tests or this is executing in the context of death test child + // process. In either case the user does not want to see pop-up dialogs + // about crashes - they are expected. + if (impl()->catch_exceptions() || in_death_test_child_process) { +# if !GTEST_OS_WINDOWS_MOBILE + // SetErrorMode doesn't exist on CE. + SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | + SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); +# endif // !GTEST_OS_WINDOWS_MOBILE + +# if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE + // Death test children can be terminated with _abort(). On Windows, + // _abort() can show a dialog with a warning message. This forces the + // abort message to go to stderr instead. + _set_error_mode(_OUT_TO_STDERR); +# endif + +# if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE + // In the debug version, Visual Studio pops up a separate dialog + // offering a choice to debug the aborted program. We need to suppress + // this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement + // executed. Google Test will notify the user of any unexpected + // failure via stderr. + // + // VC++ doesn't define _set_abort_behavior() prior to the version 8.0. + // Users of prior VC versions shall suffer the agony and pain of + // clicking through the countless debug dialogs. + // TODO(vladl@google.com): find a way to suppress the abort dialog() in the + // debug mode when compiled with VC 7.1 or lower. + if (!GTEST_FLAG(break_on_failure)) + _set_abort_behavior( + 0x0, // Clear the following flags: + _WRITE_ABORT_MSG | _CALL_REPORTFAULT); // pop-up window, core dump. +# endif + } +#endif // GTEST_HAS_SEH + + return internal::HandleExceptionsInMethodIfSupported( + impl(), + &internal::UnitTestImpl::RunAllTests, + "auxiliary test code (environments or event listeners)") ? 0 : 1; +} + +// Returns the working directory when the first TEST() or TEST_F() was +// executed. +const char* UnitTest::original_working_dir() const { + return impl_->original_working_dir_.c_str(); +} + +// Returns the TestCase object for the test that's currently running, +// or NULL if no test is running. +const TestCase* UnitTest::current_test_case() const + GTEST_LOCK_EXCLUDED_(mutex_) { + internal::MutexLock lock(&mutex_); + return impl_->current_test_case(); +} + +// Returns the TestInfo object for the test that's currently running, +// or NULL if no test is running. +const TestInfo* UnitTest::current_test_info() const + GTEST_LOCK_EXCLUDED_(mutex_) { + internal::MutexLock lock(&mutex_); + return impl_->current_test_info(); +} + +// Returns the random seed used at the start of the current test run. +int UnitTest::random_seed() const { return impl_->random_seed(); } + +#if GTEST_HAS_PARAM_TEST +// Returns ParameterizedTestCaseRegistry object used to keep track of +// value-parameterized tests and instantiate and register them. +internal::ParameterizedTestCaseRegistry& + UnitTest::parameterized_test_registry() + GTEST_LOCK_EXCLUDED_(mutex_) { + return impl_->parameterized_test_registry(); +} +#endif // GTEST_HAS_PARAM_TEST + +// Creates an empty UnitTest. +UnitTest::UnitTest() { + impl_ = new internal::UnitTestImpl(this); +} + +// Destructor of UnitTest. +UnitTest::~UnitTest() { + delete impl_; +} + +// Pushes a trace defined by SCOPED_TRACE() on to the per-thread +// Google Test trace stack. +void UnitTest::PushGTestTrace(const internal::TraceInfo& trace) + GTEST_LOCK_EXCLUDED_(mutex_) { + internal::MutexLock lock(&mutex_); + impl_->gtest_trace_stack().push_back(trace); +} + +// Pops a trace from the per-thread Google Test trace stack. +void UnitTest::PopGTestTrace() + GTEST_LOCK_EXCLUDED_(mutex_) { + internal::MutexLock lock(&mutex_); + impl_->gtest_trace_stack().pop_back(); +} + +namespace internal { + +UnitTestImpl::UnitTestImpl(UnitTest* parent) + : parent_(parent), +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4355) // Temporarily disables warning 4355 + // (using this in initializer). + default_global_test_part_result_reporter_(this), + default_per_thread_test_part_result_reporter_(this), +# pragma warning(pop) // Restores the warning state again. +#else + default_global_test_part_result_reporter_(this), + default_per_thread_test_part_result_reporter_(this), +#endif // _MSC_VER + global_test_part_result_repoter_( + &default_global_test_part_result_reporter_), + per_thread_test_part_result_reporter_( + &default_per_thread_test_part_result_reporter_), +#if GTEST_HAS_PARAM_TEST + parameterized_test_registry_(), + parameterized_tests_registered_(false), +#endif // GTEST_HAS_PARAM_TEST + last_death_test_case_(-1), + current_test_case_(NULL), + current_test_info_(NULL), + ad_hoc_test_result_(), + os_stack_trace_getter_(NULL), + post_flag_parse_init_performed_(false), + random_seed_(0), // Will be overridden by the flag before first use. + random_(0), // Will be reseeded before first use. + start_timestamp_(0), + elapsed_time_(0), +#if GTEST_HAS_DEATH_TEST + death_test_factory_(new DefaultDeathTestFactory), +#endif + // Will be overridden by the flag before first use. + catch_exceptions_(false) { + listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter); +} + +UnitTestImpl::~UnitTestImpl() { + // Deletes every TestCase. + ForEach(test_cases_, internal::Delete); + + // Deletes every Environment. + ForEach(environments_, internal::Delete); + + delete os_stack_trace_getter_; +} + +// Adds a TestProperty to the current TestResult object when invoked in a +// context of a test, to current test case's ad_hoc_test_result when invoke +// from SetUpTestCase/TearDownTestCase, or to the global property set +// otherwise. If the result already contains a property with the same key, +// the value will be updated. +void UnitTestImpl::RecordProperty(const TestProperty& test_property) { + std::string xml_element; + TestResult* test_result; // TestResult appropriate for property recording. + + if (current_test_info_ != NULL) { + xml_element = "testcase"; + test_result = &(current_test_info_->result_); + } else if (current_test_case_ != NULL) { + xml_element = "testsuite"; + test_result = &(current_test_case_->ad_hoc_test_result_); + } else { + xml_element = "testsuites"; + test_result = &ad_hoc_test_result_; + } + test_result->RecordProperty(xml_element, test_property); +} + +#if GTEST_HAS_DEATH_TEST +// Disables event forwarding if the control is currently in a death test +// subprocess. Must not be called before InitGoogleTest. +void UnitTestImpl::SuppressTestEventsIfInSubprocess() { + if (internal_run_death_test_flag_.get() != NULL) + listeners()->SuppressEventForwarding(); +} +#endif // GTEST_HAS_DEATH_TEST + +// Initializes event listeners performing XML output as specified by +// UnitTestOptions. Must not be called before InitGoogleTest. +void UnitTestImpl::ConfigureXmlOutput() { + const std::string& output_format = UnitTestOptions::GetOutputFormat(); + if (output_format == "xml") { + listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter( + UnitTestOptions::GetAbsolutePathToOutputFile().c_str())); + } else if (output_format != "") { + printf("WARNING: unrecognized output format \"%s\" ignored.\n", + output_format.c_str()); + fflush(stdout); + } +} + +#if GTEST_CAN_STREAM_RESULTS_ +// Initializes event listeners for streaming test results in string form. +// Must not be called before InitGoogleTest. +void UnitTestImpl::ConfigureStreamingOutput() { + const std::string& target = GTEST_FLAG(stream_result_to); + if (!target.empty()) { + const size_t pos = target.find(':'); + if (pos != std::string::npos) { + listeners()->Append(new StreamingListener(target.substr(0, pos), + target.substr(pos+1))); + } else { + printf("WARNING: unrecognized streaming target \"%s\" ignored.\n", + target.c_str()); + fflush(stdout); + } + } +} +#endif // GTEST_CAN_STREAM_RESULTS_ + +// Performs initialization dependent upon flag values obtained in +// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to +// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest +// this function is also called from RunAllTests. Since this function can be +// called more than once, it has to be idempotent. +void UnitTestImpl::PostFlagParsingInit() { + // Ensures that this function does not execute more than once. + if (!post_flag_parse_init_performed_) { + post_flag_parse_init_performed_ = true; + +#if GTEST_HAS_DEATH_TEST + InitDeathTestSubprocessControlInfo(); + SuppressTestEventsIfInSubprocess(); +#endif // GTEST_HAS_DEATH_TEST + + // Registers parameterized tests. This makes parameterized tests + // available to the UnitTest reflection API without running + // RUN_ALL_TESTS. + RegisterParameterizedTests(); + + // Configures listeners for XML output. This makes it possible for users + // to shut down the default XML output before invoking RUN_ALL_TESTS. + ConfigureXmlOutput(); + +#if GTEST_CAN_STREAM_RESULTS_ + // Configures listeners for streaming test results to the specified server. + ConfigureStreamingOutput(); +#endif // GTEST_CAN_STREAM_RESULTS_ + } +} + +// A predicate that checks the name of a TestCase against a known +// value. +// +// This is used for implementation of the UnitTest class only. We put +// it in the anonymous namespace to prevent polluting the outer +// namespace. +// +// TestCaseNameIs is copyable. +class TestCaseNameIs { + public: + // Constructor. + explicit TestCaseNameIs(const std::string& name) + : name_(name) {} + + // Returns true iff the name of test_case matches name_. + bool operator()(const TestCase* test_case) const { + return test_case != NULL && strcmp(test_case->name(), name_.c_str()) == 0; + } + + private: + std::string name_; +}; + +// Finds and returns a TestCase with the given name. If one doesn't +// exist, creates one and returns it. It's the CALLER'S +// RESPONSIBILITY to ensure that this function is only called WHEN THE +// TESTS ARE NOT SHUFFLED. +// +// Arguments: +// +// test_case_name: name of the test case +// type_param: the name of the test case's type parameter, or NULL if +// this is not a typed or a type-parameterized test case. +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +TestCase* UnitTestImpl::GetTestCase(const char* test_case_name, + const char* type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc) { + // Can we find a TestCase with the given name? + const std::vector::const_iterator test_case = + std::find_if(test_cases_.begin(), test_cases_.end(), + TestCaseNameIs(test_case_name)); + + if (test_case != test_cases_.end()) + return *test_case; + + // No. Let's create one. + TestCase* const new_test_case = + new TestCase(test_case_name, type_param, set_up_tc, tear_down_tc); + + // Is this a death test case? + if (internal::UnitTestOptions::MatchesFilter(test_case_name, + kDeathTestCaseFilter)) { + // Yes. Inserts the test case after the last death test case + // defined so far. This only works when the test cases haven't + // been shuffled. Otherwise we may end up running a death test + // after a non-death test. + ++last_death_test_case_; + test_cases_.insert(test_cases_.begin() + last_death_test_case_, + new_test_case); + } else { + // No. Appends to the end of the list. + test_cases_.push_back(new_test_case); + } + + test_case_indices_.push_back(static_cast(test_case_indices_.size())); + return new_test_case; +} + +// Helpers for setting up / tearing down the given environment. They +// are for use in the ForEach() function. +static void SetUpEnvironment(Environment* env) { env->SetUp(); } +static void TearDownEnvironment(Environment* env) { env->TearDown(); } + +// Runs all tests in this UnitTest object, prints the result, and +// returns true if all tests are successful. If any exception is +// thrown during a test, the test is considered to be failed, but the +// rest of the tests will still be run. +// +// When parameterized tests are enabled, it expands and registers +// parameterized tests first in RegisterParameterizedTests(). +// All other functions called from RunAllTests() may safely assume that +// parameterized tests are ready to be counted and run. +bool UnitTestImpl::RunAllTests() { + // Makes sure InitGoogleTest() was called. + if (!GTestIsInitialized()) { + printf("%s", + "\nThis test program did NOT call ::testing::InitGoogleTest " + "before calling RUN_ALL_TESTS(). Please fix it.\n"); + return false; + } + + // Do not run any test if the --help flag was specified. + if (g_help_flag) + return true; + + // Repeats the call to the post-flag parsing initialization in case the + // user didn't call InitGoogleTest. + PostFlagParsingInit(); + + // Even if sharding is not on, test runners may want to use the + // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding + // protocol. + internal::WriteToShardStatusFileIfNeeded(); + + // True iff we are in a subprocess for running a thread-safe-style + // death test. + bool in_subprocess_for_death_test = false; + +#if GTEST_HAS_DEATH_TEST + in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL); +#endif // GTEST_HAS_DEATH_TEST + + const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex, + in_subprocess_for_death_test); + + // Compares the full test names with the filter to decide which + // tests to run. + const bool has_tests_to_run = FilterTests(should_shard + ? HONOR_SHARDING_PROTOCOL + : IGNORE_SHARDING_PROTOCOL) > 0; + + // Lists the tests and exits if the --gtest_list_tests flag was specified. + if (GTEST_FLAG(list_tests)) { + // This must be called *after* FilterTests() has been called. + ListTestsMatchingFilter(); + return true; + } + + random_seed_ = GTEST_FLAG(shuffle) ? + GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0; + + // True iff at least one test has failed. + bool failed = false; + + TestEventListener* repeater = listeners()->repeater(); + + start_timestamp_ = GetTimeInMillis(); + repeater->OnTestProgramStart(*parent_); + + // How many times to repeat the tests? We don't want to repeat them + // when we are inside the subprocess of a death test. + const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat); + // Repeats forever if the repeat count is negative. + const bool forever = repeat < 0; + for (int i = 0; forever || i != repeat; i++) { + // We want to preserve failures generated by ad-hoc test + // assertions executed before RUN_ALL_TESTS(). + ClearNonAdHocTestResult(); + + const TimeInMillis start = GetTimeInMillis(); + + // Shuffles test cases and tests if requested. + if (has_tests_to_run && GTEST_FLAG(shuffle)) { + random()->Reseed(random_seed_); + // This should be done before calling OnTestIterationStart(), + // such that a test event listener can see the actual test order + // in the event. + ShuffleTests(); + } + + // Tells the unit test event listeners that the tests are about to start. + repeater->OnTestIterationStart(*parent_, i); + + // Runs each test case if there is at least one test to run. + if (has_tests_to_run) { + // Sets up all environments beforehand. + repeater->OnEnvironmentsSetUpStart(*parent_); + ForEach(environments_, SetUpEnvironment); + repeater->OnEnvironmentsSetUpEnd(*parent_); + + // Runs the tests only if there was no fatal failure during global + // set-up. + if (!Test::HasFatalFailure()) { + for (int test_index = 0; test_index < total_test_case_count(); + test_index++) { + GetMutableTestCase(test_index)->Run(); + } + } + + // Tears down all environments in reverse order afterwards. + repeater->OnEnvironmentsTearDownStart(*parent_); + std::for_each(environments_.rbegin(), environments_.rend(), + TearDownEnvironment); + repeater->OnEnvironmentsTearDownEnd(*parent_); + } + + elapsed_time_ = GetTimeInMillis() - start; + + // Tells the unit test event listener that the tests have just finished. + repeater->OnTestIterationEnd(*parent_, i); + + // Gets the result and clears it. + if (!Passed()) { + failed = true; + } + + // Restores the original test order after the iteration. This + // allows the user to quickly repro a failure that happens in the + // N-th iteration without repeating the first (N - 1) iterations. + // This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in + // case the user somehow changes the value of the flag somewhere + // (it's always safe to unshuffle the tests). + UnshuffleTests(); + + if (GTEST_FLAG(shuffle)) { + // Picks a new random seed for each iteration. + random_seed_ = GetNextRandomSeed(random_seed_); + } + } + + repeater->OnTestProgramEnd(*parent_); + + return !failed; +} + +// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file +// if the variable is present. If a file already exists at this location, this +// function will write over it. If the variable is present, but the file cannot +// be created, prints an error and exits. +void WriteToShardStatusFileIfNeeded() { + const char* const test_shard_file = posix::GetEnv(kTestShardStatusFile); + if (test_shard_file != NULL) { + FILE* const file = posix::FOpen(test_shard_file, "w"); + if (file == NULL) { + ColoredPrintf(COLOR_RED, + "Could not write to the test shard status file \"%s\" " + "specified by the %s environment variable.\n", + test_shard_file, kTestShardStatusFile); + fflush(stdout); + exit(EXIT_FAILURE); + } + fclose(file); + } +} + +// Checks whether sharding is enabled by examining the relevant +// environment variable values. If the variables are present, +// but inconsistent (i.e., shard_index >= total_shards), prints +// an error and exits. If in_subprocess_for_death_test, sharding is +// disabled because it must only be applied to the original test +// process. Otherwise, we could filter out death tests we intended to execute. +bool ShouldShard(const char* total_shards_env, + const char* shard_index_env, + bool in_subprocess_for_death_test) { + if (in_subprocess_for_death_test) { + return false; + } + + const Int32 total_shards = Int32FromEnvOrDie(total_shards_env, -1); + const Int32 shard_index = Int32FromEnvOrDie(shard_index_env, -1); + + if (total_shards == -1 && shard_index == -1) { + return false; + } else if (total_shards == -1 && shard_index != -1) { + const Message msg = Message() + << "Invalid environment variables: you have " + << kTestShardIndex << " = " << shard_index + << ", but have left " << kTestTotalShards << " unset.\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } else if (total_shards != -1 && shard_index == -1) { + const Message msg = Message() + << "Invalid environment variables: you have " + << kTestTotalShards << " = " << total_shards + << ", but have left " << kTestShardIndex << " unset.\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } else if (shard_index < 0 || shard_index >= total_shards) { + const Message msg = Message() + << "Invalid environment variables: we require 0 <= " + << kTestShardIndex << " < " << kTestTotalShards + << ", but you have " << kTestShardIndex << "=" << shard_index + << ", " << kTestTotalShards << "=" << total_shards << ".\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } + + return total_shards > 1; +} + +// Parses the environment variable var as an Int32. If it is unset, +// returns default_val. If it is not an Int32, prints an error +// and aborts. +Int32 Int32FromEnvOrDie(const char* var, Int32 default_val) { + const char* str_val = posix::GetEnv(var); + if (str_val == NULL) { + return default_val; + } + + Int32 result; + if (!ParseInt32(Message() << "The value of environment variable " << var, + str_val, &result)) { + exit(EXIT_FAILURE); + } + return result; +} + +// Given the total number of shards, the shard index, and the test id, +// returns true iff the test should be run on this shard. The test id is +// some arbitrary but unique non-negative integer assigned to each test +// method. Assumes that 0 <= shard_index < total_shards. +bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) { + return (test_id % total_shards) == shard_index; +} + +// Compares the name of each test with the user-specified filter to +// decide whether the test should be run, then records the result in +// each TestCase and TestInfo object. +// If shard_tests == true, further filters tests based on sharding +// variables in the environment - see +// http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide. +// Returns the number of tests that should run. +int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) { + const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ? + Int32FromEnvOrDie(kTestTotalShards, -1) : -1; + const Int32 shard_index = shard_tests == HONOR_SHARDING_PROTOCOL ? + Int32FromEnvOrDie(kTestShardIndex, -1) : -1; + + // num_runnable_tests are the number of tests that will + // run across all shards (i.e., match filter and are not disabled). + // num_selected_tests are the number of tests to be run on + // this shard. + int num_runnable_tests = 0; + int num_selected_tests = 0; + for (size_t i = 0; i < test_cases_.size(); i++) { + TestCase* const test_case = test_cases_[i]; + const std::string &test_case_name = test_case->name(); + test_case->set_should_run(false); + + for (size_t j = 0; j < test_case->test_info_list().size(); j++) { + TestInfo* const test_info = test_case->test_info_list()[j]; + const std::string test_name(test_info->name()); + // A test is disabled if test case name or test name matches + // kDisableTestFilter. + const bool is_disabled = + internal::UnitTestOptions::MatchesFilter(test_case_name, + kDisableTestFilter) || + internal::UnitTestOptions::MatchesFilter(test_name, + kDisableTestFilter); + test_info->is_disabled_ = is_disabled; + + const bool matches_filter = + internal::UnitTestOptions::FilterMatchesTest(test_case_name, + test_name); + test_info->matches_filter_ = matches_filter; + + const bool is_runnable = + (GTEST_FLAG(also_run_disabled_tests) || !is_disabled) && + matches_filter; + + const bool is_selected = is_runnable && + (shard_tests == IGNORE_SHARDING_PROTOCOL || + ShouldRunTestOnShard(total_shards, shard_index, + num_runnable_tests)); + + num_runnable_tests += is_runnable; + num_selected_tests += is_selected; + + test_info->should_run_ = is_selected; + test_case->set_should_run(test_case->should_run() || is_selected); + } + } + return num_selected_tests; +} + +// Prints the given C-string on a single line by replacing all '\n' +// characters with string "\\n". If the output takes more than +// max_length characters, only prints the first max_length characters +// and "...". +static void PrintOnOneLine(const char* str, int max_length) { + if (str != NULL) { + for (int i = 0; *str != '\0'; ++str) { + if (i >= max_length) { + printf("..."); + break; + } + if (*str == '\n') { + printf("\\n"); + i += 2; + } else { + printf("%c", *str); + ++i; + } + } + } +} + +// Prints the names of the tests matching the user-specified filter flag. +void UnitTestImpl::ListTestsMatchingFilter() { + // Print at most this many characters for each type/value parameter. + const int kMaxParamLength = 250; + + for (size_t i = 0; i < test_cases_.size(); i++) { + const TestCase* const test_case = test_cases_[i]; + bool printed_test_case_name = false; + + for (size_t j = 0; j < test_case->test_info_list().size(); j++) { + const TestInfo* const test_info = + test_case->test_info_list()[j]; + if (test_info->matches_filter_) { + if (!printed_test_case_name) { + printed_test_case_name = true; + printf("%s.", test_case->name()); + if (test_case->type_param() != NULL) { + printf(" # %s = ", kTypeParamLabel); + // We print the type parameter on a single line to make + // the output easy to parse by a program. + PrintOnOneLine(test_case->type_param(), kMaxParamLength); + } + printf("\n"); + } + printf(" %s", test_info->name()); + if (test_info->value_param() != NULL) { + printf(" # %s = ", kValueParamLabel); + // We print the value parameter on a single line to make the + // output easy to parse by a program. + PrintOnOneLine(test_info->value_param(), kMaxParamLength); + } + printf("\n"); + } + } + } + fflush(stdout); +} + +// Sets the OS stack trace getter. +// +// Does nothing if the input and the current OS stack trace getter are +// the same; otherwise, deletes the old getter and makes the input the +// current getter. +void UnitTestImpl::set_os_stack_trace_getter( + OsStackTraceGetterInterface* getter) { + if (os_stack_trace_getter_ != getter) { + delete os_stack_trace_getter_; + os_stack_trace_getter_ = getter; + } +} + +// Returns the current OS stack trace getter if it is not NULL; +// otherwise, creates an OsStackTraceGetter, makes it the current +// getter, and returns it. +OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() { + if (os_stack_trace_getter_ == NULL) { + os_stack_trace_getter_ = new OsStackTraceGetter; + } + + return os_stack_trace_getter_; +} + +// Returns the TestResult for the test that's currently running, or +// the TestResult for the ad hoc test if no test is running. +TestResult* UnitTestImpl::current_test_result() { + return current_test_info_ ? + &(current_test_info_->result_) : &ad_hoc_test_result_; +} + +// Shuffles all test cases, and the tests within each test case, +// making sure that death tests are still run first. +void UnitTestImpl::ShuffleTests() { + // Shuffles the death test cases. + ShuffleRange(random(), 0, last_death_test_case_ + 1, &test_case_indices_); + + // Shuffles the non-death test cases. + ShuffleRange(random(), last_death_test_case_ + 1, + static_cast(test_cases_.size()), &test_case_indices_); + + // Shuffles the tests inside each test case. + for (size_t i = 0; i < test_cases_.size(); i++) { + test_cases_[i]->ShuffleTests(random()); + } +} + +// Restores the test cases and tests to their order before the first shuffle. +void UnitTestImpl::UnshuffleTests() { + for (size_t i = 0; i < test_cases_.size(); i++) { + // Unshuffles the tests in each test case. + test_cases_[i]->UnshuffleTests(); + // Resets the index of each test case. + test_case_indices_[i] = static_cast(i); + } +} + +// Returns the current OS stack trace as an std::string. +// +// The maximum number of stack frames to be included is specified by +// the gtest_stack_trace_depth flag. The skip_count parameter +// specifies the number of top frames to be skipped, which doesn't +// count against the number of frames to be included. +// +// For example, if Foo() calls Bar(), which in turn calls +// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in +// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't. +std::string GetCurrentOsStackTraceExceptTop(UnitTest* /*unit_test*/, + int skip_count) { + // We pass skip_count + 1 to skip this wrapper function in addition + // to what the user really wants to skip. + return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1); +} + +// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to +// suppress unreachable code warnings. +namespace { +class ClassUniqueToAlwaysTrue {}; +} + +bool IsTrue(bool condition) { return condition; } + +bool AlwaysTrue() { +#if GTEST_HAS_EXCEPTIONS + // This condition is always false so AlwaysTrue() never actually throws, + // but it makes the compiler think that it may throw. + if (IsTrue(false)) + throw ClassUniqueToAlwaysTrue(); +#endif // GTEST_HAS_EXCEPTIONS + return true; +} + +// If *pstr starts with the given prefix, modifies *pstr to be right +// past the prefix and returns true; otherwise leaves *pstr unchanged +// and returns false. None of pstr, *pstr, and prefix can be NULL. +bool SkipPrefix(const char* prefix, const char** pstr) { + const size_t prefix_len = strlen(prefix); + if (strncmp(*pstr, prefix, prefix_len) == 0) { + *pstr += prefix_len; + return true; + } + return false; +} + +// Parses a string as a command line flag. The string should have +// the format "--flag=value". When def_optional is true, the "=value" +// part can be omitted. +// +// Returns the value of the flag, or NULL if the parsing failed. +const char* ParseFlagValue(const char* str, + const char* flag, + bool def_optional) { + // str and flag must not be NULL. + if (str == NULL || flag == NULL) return NULL; + + // The flag must start with "--" followed by GTEST_FLAG_PREFIX_. + const std::string flag_str = std::string("--") + GTEST_FLAG_PREFIX_ + flag; + const size_t flag_len = flag_str.length(); + if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL; + + // Skips the flag name. + const char* flag_end = str + flag_len; + + // When def_optional is true, it's OK to not have a "=value" part. + if (def_optional && (flag_end[0] == '\0')) { + return flag_end; + } + + // If def_optional is true and there are more characters after the + // flag name, or if def_optional is false, there must be a '=' after + // the flag name. + if (flag_end[0] != '=') return NULL; + + // Returns the string after "=". + return flag_end + 1; +} + +// Parses a string for a bool flag, in the form of either +// "--flag=value" or "--flag". +// +// In the former case, the value is taken as true as long as it does +// not start with '0', 'f', or 'F'. +// +// In the latter case, the value is taken as true. +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseBoolFlag(const char* str, const char* flag, bool* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(str, flag, true); + + // Aborts if the parsing failed. + if (value_str == NULL) return false; + + // Converts the string value to a bool. + *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F'); + return true; +} + +// Parses a string for an Int32 flag, in the form of +// "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseInt32Flag(const char* str, const char* flag, Int32* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(str, flag, false); + + // Aborts if the parsing failed. + if (value_str == NULL) return false; + + // Sets *value to the value of the flag. + return ParseInt32(Message() << "The value of flag --" << flag, + value_str, value); +} + +// Parses a string for a string flag, in the form of +// "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseStringFlag(const char* str, const char* flag, std::string* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(str, flag, false); + + // Aborts if the parsing failed. + if (value_str == NULL) return false; + + // Sets *value to the value of the flag. + *value = value_str; + return true; +} + +// Determines whether a string has a prefix that Google Test uses for its +// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_. +// If Google Test detects that a command line flag has its prefix but is not +// recognized, it will print its help message. Flags starting with +// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test +// internal flags and do not trigger the help message. +static bool HasGoogleTestFlagPrefix(const char* str) { + return (SkipPrefix("--", &str) || + SkipPrefix("-", &str) || + SkipPrefix("/", &str)) && + !SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) && + (SkipPrefix(GTEST_FLAG_PREFIX_, &str) || + SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str)); +} + +// Prints a string containing code-encoded text. The following escape +// sequences can be used in the string to control the text color: +// +// @@ prints a single '@' character. +// @R changes the color to red. +// @G changes the color to green. +// @Y changes the color to yellow. +// @D changes to the default terminal text color. +// +// TODO(wan@google.com): Write tests for this once we add stdout +// capturing to Google Test. +static void PrintColorEncoded(const char* str) { + GTestColor color = COLOR_DEFAULT; // The current color. + + // Conceptually, we split the string into segments divided by escape + // sequences. Then we print one segment at a time. At the end of + // each iteration, the str pointer advances to the beginning of the + // next segment. + for (;;) { + const char* p = strchr(str, '@'); + if (p == NULL) { + ColoredPrintf(color, "%s", str); + return; + } + + ColoredPrintf(color, "%s", std::string(str, p).c_str()); + + const char ch = p[1]; + str = p + 2; + if (ch == '@') { + ColoredPrintf(color, "@"); + } else if (ch == 'D') { + color = COLOR_DEFAULT; + } else if (ch == 'R') { + color = COLOR_RED; + } else if (ch == 'G') { + color = COLOR_GREEN; + } else if (ch == 'Y') { + color = COLOR_YELLOW; + } else { + --str; + } + } +} + +static const char kColorEncodedHelpMessage[] = +"This program contains tests written using " GTEST_NAME_ ". You can use the\n" +"following command line flags to control its behavior:\n" +"\n" +"Test Selection:\n" +" @G--" GTEST_FLAG_PREFIX_ "list_tests@D\n" +" List the names of all tests instead of running them. The name of\n" +" TEST(Foo, Bar) is \"Foo.Bar\".\n" +" @G--" GTEST_FLAG_PREFIX_ "filter=@YPOSTIVE_PATTERNS" + "[@G-@YNEGATIVE_PATTERNS]@D\n" +" Run only the tests whose name matches one of the positive patterns but\n" +" none of the negative patterns. '?' matches any single character; '*'\n" +" matches any substring; ':' separates two patterns.\n" +" @G--" GTEST_FLAG_PREFIX_ "also_run_disabled_tests@D\n" +" Run all disabled tests too.\n" +"\n" +"Test Execution:\n" +" @G--" GTEST_FLAG_PREFIX_ "repeat=@Y[COUNT]@D\n" +" Run the tests repeatedly; use a negative count to repeat forever.\n" +" @G--" GTEST_FLAG_PREFIX_ "shuffle@D\n" +" Randomize tests' orders on every iteration.\n" +" @G--" GTEST_FLAG_PREFIX_ "random_seed=@Y[NUMBER]@D\n" +" Random number seed to use for shuffling test orders (between 1 and\n" +" 99999, or 0 to use a seed based on the current time).\n" +"\n" +"Test Output:\n" +" @G--" GTEST_FLAG_PREFIX_ "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\n" +" Enable/disable colored output. The default is @Gauto@D.\n" +" -@G-" GTEST_FLAG_PREFIX_ "print_time=0@D\n" +" Don't print the elapsed time of each test.\n" +" @G--" GTEST_FLAG_PREFIX_ "output=xml@Y[@G:@YDIRECTORY_PATH@G" + GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n" +" Generate an XML report in the given directory or with the given file\n" +" name. @YFILE_PATH@D defaults to @Gtest_details.xml@D.\n" +#if GTEST_CAN_STREAM_RESULTS_ +" @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST@G:@YPORT@D\n" +" Stream test results to the given server.\n" +#endif // GTEST_CAN_STREAM_RESULTS_ +"\n" +"Assertion Behavior:\n" +#if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS +" @G--" GTEST_FLAG_PREFIX_ "death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n" +" Set the default death test style.\n" +#endif // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS +" @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n" +" Turn assertion failures into debugger break-points.\n" +" @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n" +" Turn assertion failures into C++ exceptions.\n" +" @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n" +" Do not report exceptions as test failures. Instead, allow them\n" +" to crash the program or throw a pop-up (on Windows).\n" +"\n" +"Except for @G--" GTEST_FLAG_PREFIX_ "list_tests@D, you can alternatively set " + "the corresponding\n" +"environment variable of a flag (all letters in upper-case). For example, to\n" +"disable colored text output, you can either specify @G--" GTEST_FLAG_PREFIX_ + "color=no@D or set\n" +"the @G" GTEST_FLAG_PREFIX_UPPER_ "COLOR@D environment variable to @Gno@D.\n" +"\n" +"For more information, please read the " GTEST_NAME_ " documentation at\n" +"@G" GTEST_PROJECT_URL_ "@D. If you find a bug in " GTEST_NAME_ "\n" +"(not one in your own code or tests), please report it to\n" +"@G<" GTEST_DEV_EMAIL_ ">@D.\n"; + +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. The type parameter CharType can be +// instantiated to either char or wchar_t. +template +void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) { + for (int i = 1; i < *argc; i++) { + const std::string arg_string = StreamableToString(argv[i]); + const char* const arg = arg_string.c_str(); + + using internal::ParseBoolFlag; + using internal::ParseInt32Flag; + using internal::ParseStringFlag; + + // Do we see a Google Test flag? + if (ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag, + >EST_FLAG(also_run_disabled_tests)) || + ParseBoolFlag(arg, kBreakOnFailureFlag, + >EST_FLAG(break_on_failure)) || + ParseBoolFlag(arg, kCatchExceptionsFlag, + >EST_FLAG(catch_exceptions)) || + ParseStringFlag(arg, kColorFlag, >EST_FLAG(color)) || + ParseStringFlag(arg, kDeathTestStyleFlag, + >EST_FLAG(death_test_style)) || + ParseBoolFlag(arg, kDeathTestUseFork, + >EST_FLAG(death_test_use_fork)) || + ParseStringFlag(arg, kFilterFlag, >EST_FLAG(filter)) || + ParseStringFlag(arg, kInternalRunDeathTestFlag, + >EST_FLAG(internal_run_death_test)) || + ParseBoolFlag(arg, kListTestsFlag, >EST_FLAG(list_tests)) || + ParseStringFlag(arg, kOutputFlag, >EST_FLAG(output)) || + ParseBoolFlag(arg, kPrintTimeFlag, >EST_FLAG(print_time)) || + ParseInt32Flag(arg, kRandomSeedFlag, >EST_FLAG(random_seed)) || + ParseInt32Flag(arg, kRepeatFlag, >EST_FLAG(repeat)) || + ParseBoolFlag(arg, kShuffleFlag, >EST_FLAG(shuffle)) || + ParseInt32Flag(arg, kStackTraceDepthFlag, + >EST_FLAG(stack_trace_depth)) || + ParseStringFlag(arg, kStreamResultToFlag, + >EST_FLAG(stream_result_to)) || + ParseBoolFlag(arg, kThrowOnFailureFlag, + >EST_FLAG(throw_on_failure)) + ) { + // Yes. Shift the remainder of the argv list left by one. Note + // that argv has (*argc + 1) elements, the last one always being + // NULL. The following loop moves the trailing NULL element as + // well. + for (int j = i; j != *argc; j++) { + argv[j] = argv[j + 1]; + } + + // Decrements the argument count. + (*argc)--; + + // We also need to decrement the iterator as we just removed + // an element. + i--; + } else if (arg_string == "--help" || arg_string == "-h" || + arg_string == "-?" || arg_string == "/?" || + HasGoogleTestFlagPrefix(arg)) { + // Both help flag and unrecognized Google Test flags (excluding + // internal ones) trigger help display. + g_help_flag = true; + } + } + + if (g_help_flag) { + // We print the help here instead of in RUN_ALL_TESTS(), as the + // latter may not be called at all if the user is using Google + // Test with another testing framework. + PrintColorEncoded(kColorEncodedHelpMessage); + } +} + +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. +void ParseGoogleTestFlagsOnly(int* argc, char** argv) { + ParseGoogleTestFlagsOnlyImpl(argc, argv); +} +void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv) { + ParseGoogleTestFlagsOnlyImpl(argc, argv); +} + +// The internal implementation of InitGoogleTest(). +// +// The type parameter CharType can be instantiated to either char or +// wchar_t. +template +void InitGoogleTestImpl(int* argc, CharType** argv) { + g_init_gtest_count++; + + // We don't want to run the initialization code twice. + if (g_init_gtest_count != 1) return; + + if (*argc <= 0) return; + + internal::g_executable_path = internal::StreamableToString(argv[0]); + +#if GTEST_HAS_DEATH_TEST + + g_argvs.clear(); + for (int i = 0; i != *argc; i++) { + g_argvs.push_back(StreamableToString(argv[i])); + } + +#endif // GTEST_HAS_DEATH_TEST + + ParseGoogleTestFlagsOnly(argc, argv); + GetUnitTestImpl()->PostFlagParsingInit(); +} + +} // namespace internal + +// Initializes Google Test. This must be called before calling +// RUN_ALL_TESTS(). In particular, it parses a command line for the +// flags that Google Test recognizes. Whenever a Google Test flag is +// seen, it is removed from argv, and *argc is decremented. +// +// No value is returned. Instead, the Google Test flag variables are +// updated. +// +// Calling the function for the second time has no user-visible effect. +void InitGoogleTest(int* argc, char** argv) { + internal::InitGoogleTestImpl(argc, argv); +} + +// This overloaded version can be used in Windows programs compiled in +// UNICODE mode. +void InitGoogleTest(int* argc, wchar_t** argv) { + internal::InitGoogleTestImpl(argc, argv); +} + +} // namespace testing +// 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 +// 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), vladl@google.com (Vlad Losev) +// +// This file implements death tests. + + +#if GTEST_HAS_DEATH_TEST + +# if GTEST_OS_MAC +# include +# endif // GTEST_OS_MAC + +# include +# include +# include + +# if GTEST_OS_LINUX +# include +# endif // GTEST_OS_LINUX + +# include + +# if GTEST_OS_WINDOWS +# include +# else +# include +# include +# endif // GTEST_OS_WINDOWS + +# if GTEST_OS_QNX +# include +# endif // GTEST_OS_QNX + +#endif // GTEST_HAS_DEATH_TEST + + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +#undef GTEST_IMPLEMENTATION_ + +namespace testing { + +// Constants. + +// The default death test style. +static const char kDefaultDeathTestStyle[] = "fast"; + +GTEST_DEFINE_string_( + death_test_style, + internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle), + "Indicates how to run a death test in a forked child process: " + "\"threadsafe\" (child process re-executes the test binary " + "from the beginning, running only the specific death test) or " + "\"fast\" (child process runs the death test immediately " + "after forking)."); + +GTEST_DEFINE_bool_( + death_test_use_fork, + internal::BoolFromGTestEnv("death_test_use_fork", false), + "Instructs to use fork()/_exit() instead of clone() in death tests. " + "Ignored and always uses fork() on POSIX systems where clone() is not " + "implemented. Useful when running under valgrind or similar tools if " + "those do not support clone(). Valgrind 3.3.1 will just fail if " + "it sees an unsupported combination of clone() flags. " + "It is not recommended to use this flag w/o valgrind though it will " + "work in 99% of the cases. Once valgrind is fixed, this flag will " + "most likely be removed."); + +namespace internal { +GTEST_DEFINE_string_( + internal_run_death_test, "", + "Indicates the file, line number, temporal index of " + "the single death test to run, and a file descriptor to " + "which a success code may be sent, all separated by " + "the '|' characters. This flag is specified if and only if the current " + "process is a sub-process launched for running a thread-safe " + "death test. FOR INTERNAL USE ONLY."); +} // namespace internal + +#if GTEST_HAS_DEATH_TEST + +namespace internal { + +// Valid only for fast death tests. Indicates the code is running in the +// child process of a fast style death test. +static bool g_in_fast_death_test_child = false; + +// Returns a Boolean value indicating whether the caller is currently +// executing in the context of the death test child process. Tools such as +// Valgrind heap checkers may need this to modify their behavior in death +// tests. IMPORTANT: This is an internal utility. Using it may break the +// implementation of death tests. User code MUST NOT use it. +bool InDeathTestChild() { +# if GTEST_OS_WINDOWS + + // On Windows, death tests are thread-safe regardless of the value of the + // death_test_style flag. + return !GTEST_FLAG(internal_run_death_test).empty(); + +# else + + if (GTEST_FLAG(death_test_style) == "threadsafe") + return !GTEST_FLAG(internal_run_death_test).empty(); + else + return g_in_fast_death_test_child; +#endif +} + +} // namespace internal + +// ExitedWithCode constructor. +ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) { +} + +// ExitedWithCode function-call operator. +bool ExitedWithCode::operator()(int exit_status) const { +# if GTEST_OS_WINDOWS + + return exit_status == exit_code_; + +# else + + return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_; + +# endif // GTEST_OS_WINDOWS +} + +# if !GTEST_OS_WINDOWS +// KilledBySignal constructor. +KilledBySignal::KilledBySignal(int signum) : signum_(signum) { +} + +// KilledBySignal function-call operator. +bool KilledBySignal::operator()(int exit_status) const { + return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_; +} +# endif // !GTEST_OS_WINDOWS + +namespace internal { + +// Utilities needed for death tests. + +// Generates a textual description of a given exit code, in the format +// specified by wait(2). +static std::string ExitSummary(int exit_code) { + Message m; + +# if GTEST_OS_WINDOWS + + m << "Exited with exit status " << exit_code; + +# else + + if (WIFEXITED(exit_code)) { + m << "Exited with exit status " << WEXITSTATUS(exit_code); + } else if (WIFSIGNALED(exit_code)) { + m << "Terminated by signal " << WTERMSIG(exit_code); + } +# ifdef WCOREDUMP + if (WCOREDUMP(exit_code)) { + m << " (core dumped)"; + } +# endif +# endif // GTEST_OS_WINDOWS + + return m.GetString(); +} + +// Returns true if exit_status describes a process that was terminated +// by a signal, or exited normally with a nonzero exit code. +bool ExitedUnsuccessfully(int exit_status) { + return !ExitedWithCode(0)(exit_status); +} + +# if !GTEST_OS_WINDOWS +// Generates a textual failure message when a death test finds more than +// one thread running, or cannot determine the number of threads, prior +// to executing the given statement. It is the responsibility of the +// caller not to pass a thread_count of 1. +static std::string DeathTestThreadWarning(size_t thread_count) { + Message msg; + msg << "Death tests use fork(), which is unsafe particularly" + << " in a threaded context. For this test, " << GTEST_NAME_ << " "; + if (thread_count == 0) + msg << "couldn't detect the number of threads."; + else + msg << "detected " << thread_count << " threads."; + return msg.GetString(); +} +# endif // !GTEST_OS_WINDOWS + +// Flag characters for reporting a death test that did not die. +static const char kDeathTestLived = 'L'; +static const char kDeathTestReturned = 'R'; +static const char kDeathTestThrew = 'T'; +static const char kDeathTestInternalError = 'I'; + +// An enumeration describing all of the possible ways that a death test can +// conclude. DIED means that the process died while executing the test +// code; LIVED means that process lived beyond the end of the test code; +// RETURNED means that the test statement attempted to execute a return +// statement, which is not allowed; THREW means that the test statement +// returned control by throwing an exception. IN_PROGRESS means the test +// has not yet concluded. +// TODO(vladl@google.com): Unify names and possibly values for +// AbortReason, DeathTestOutcome, and flag characters above. +enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW }; + +// Routine for aborting the program which is safe to call from an +// exec-style death test child process, in which case the error +// message is propagated back to the parent process. Otherwise, the +// message is simply printed to stderr. In either case, the program +// then exits with status 1. +void DeathTestAbort(const std::string& message) { + // On a POSIX system, this function may be called from a threadsafe-style + // death test child process, which operates on a very small stack. Use + // the heap for any additional non-minuscule memory requirements. + const InternalRunDeathTestFlag* const flag = + GetUnitTestImpl()->internal_run_death_test_flag(); + if (flag != NULL) { + FILE* parent = posix::FDOpen(flag->write_fd(), "w"); + fputc(kDeathTestInternalError, parent); + fprintf(parent, "%s", message.c_str()); + fflush(parent); + _exit(1); + } else { + fprintf(stderr, "%s", message.c_str()); + fflush(stderr); + posix::Abort(); + } +} + +// A replacement for CHECK that calls DeathTestAbort if the assertion +// fails. +# define GTEST_DEATH_TEST_CHECK_(expression) \ + do { \ + if (!::testing::internal::IsTrue(expression)) { \ + DeathTestAbort( \ + ::std::string("CHECK failed: File ") + __FILE__ + ", line " \ + + ::testing::internal::StreamableToString(__LINE__) + ": " \ + + #expression); \ + } \ + } while (::testing::internal::AlwaysFalse()) + +// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for +// evaluating any system call that fulfills two conditions: it must return +// -1 on failure, and set errno to EINTR when it is interrupted and +// should be tried again. The macro expands to a loop that repeatedly +// evaluates the expression as long as it evaluates to -1 and sets +// errno to EINTR. If the expression evaluates to -1 but errno is +// something other than EINTR, DeathTestAbort is called. +# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \ + do { \ + int gtest_retval; \ + do { \ + gtest_retval = (expression); \ + } while (gtest_retval == -1 && errno == EINTR); \ + if (gtest_retval == -1) { \ + DeathTestAbort( \ + ::std::string("CHECK failed: File ") + __FILE__ + ", line " \ + + ::testing::internal::StreamableToString(__LINE__) + ": " \ + + #expression + " != -1"); \ + } \ + } while (::testing::internal::AlwaysFalse()) + +// Returns the message describing the last system error in errno. +std::string GetLastErrnoDescription() { + return errno == 0 ? "" : posix::StrError(errno); +} + +// This is called from a death test parent process to read a failure +// message from the death test child process and log it with the FATAL +// severity. On Windows, the message is read from a pipe handle. On other +// platforms, it is read from a file descriptor. +static void FailFromInternalError(int fd) { + Message error; + char buffer[256]; + int num_read; + + do { + while ((num_read = posix::Read(fd, buffer, 255)) > 0) { + buffer[num_read] = '\0'; + error << buffer; + } + } while (num_read == -1 && errno == EINTR); + + if (num_read == 0) { + GTEST_LOG_(FATAL) << error.GetString(); + } else { + const int last_error = errno; + GTEST_LOG_(FATAL) << "Error while reading death test internal: " + << GetLastErrnoDescription() << " [" << last_error << "]"; + } +} + +// Death test constructor. Increments the running death test count +// for the current test. +DeathTest::DeathTest() { + TestInfo* const info = GetUnitTestImpl()->current_test_info(); + if (info == NULL) { + DeathTestAbort("Cannot run a death test outside of a TEST or " + "TEST_F construct"); + } +} + +// Creates and returns a death test by dispatching to the current +// death test factory. +bool DeathTest::Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test) { + return GetUnitTestImpl()->death_test_factory()->Create( + statement, regex, file, line, test); +} + +const char* DeathTest::LastMessage() { + return last_death_test_message_.c_str(); +} + +void DeathTest::set_last_death_test_message(const std::string& message) { + last_death_test_message_ = message; +} + +std::string DeathTest::last_death_test_message_; + +// Provides cross platform implementation for some death functionality. +class DeathTestImpl : public DeathTest { + protected: + DeathTestImpl(const char* a_statement, const RE* a_regex) + : statement_(a_statement), + regex_(a_regex), + spawned_(false), + status_(-1), + outcome_(IN_PROGRESS), + read_fd_(-1), + write_fd_(-1) {} + + // read_fd_ is expected to be closed and cleared by a derived class. + ~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); } + + void Abort(AbortReason reason); + virtual bool Passed(bool status_ok); + + const char* statement() const { return statement_; } + const RE* regex() const { return regex_; } + bool spawned() const { return spawned_; } + void set_spawned(bool is_spawned) { spawned_ = is_spawned; } + int status() const { return status_; } + void set_status(int a_status) { status_ = a_status; } + DeathTestOutcome outcome() const { return outcome_; } + void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; } + int read_fd() const { return read_fd_; } + void set_read_fd(int fd) { read_fd_ = fd; } + int write_fd() const { return write_fd_; } + void set_write_fd(int fd) { write_fd_ = fd; } + + // Called in the parent process only. Reads the result code of the death + // test child process via a pipe, interprets it to set the outcome_ + // member, and closes read_fd_. Outputs diagnostics and terminates in + // case of unexpected codes. + void ReadAndInterpretStatusByte(); + + private: + // The textual content of the code this object is testing. This class + // doesn't own this string and should not attempt to delete it. + const char* const statement_; + // The regular expression which test output must match. DeathTestImpl + // doesn't own this object and should not attempt to delete it. + const RE* const regex_; + // True if the death test child process has been successfully spawned. + bool spawned_; + // The exit status of the child process. + int status_; + // How the death test concluded. + DeathTestOutcome outcome_; + // Descriptor to the read end of the pipe to the child process. It is + // always -1 in the child process. The child keeps its write end of the + // pipe in write_fd_. + int read_fd_; + // Descriptor to the child's write end of the pipe to the parent process. + // It is always -1 in the parent process. The parent keeps its end of the + // pipe in read_fd_. + int write_fd_; +}; + +// Called in the parent process only. Reads the result code of the death +// test child process via a pipe, interprets it to set the outcome_ +// member, and closes read_fd_. Outputs diagnostics and terminates in +// case of unexpected codes. +void DeathTestImpl::ReadAndInterpretStatusByte() { + char flag; + int bytes_read; + + // The read() here blocks until data is available (signifying the + // failure of the death test) or until the pipe is closed (signifying + // its success), so it's okay to call this in the parent before + // the child process has exited. + do { + bytes_read = posix::Read(read_fd(), &flag, 1); + } while (bytes_read == -1 && errno == EINTR); + + if (bytes_read == 0) { + set_outcome(DIED); + } else if (bytes_read == 1) { + switch (flag) { + case kDeathTestReturned: + set_outcome(RETURNED); + break; + case kDeathTestThrew: + set_outcome(THREW); + break; + case kDeathTestLived: + set_outcome(LIVED); + break; + case kDeathTestInternalError: + FailFromInternalError(read_fd()); // Does not return. + break; + default: + GTEST_LOG_(FATAL) << "Death test child process reported " + << "unexpected status byte (" + << static_cast(flag) << ")"; + } + } else { + GTEST_LOG_(FATAL) << "Read from death test child process failed: " + << GetLastErrnoDescription(); + } + GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd())); + set_read_fd(-1); +} + +// Signals that the death test code which should have exited, didn't. +// Should be called only in a death test child process. +// Writes a status byte to the child's status file descriptor, then +// calls _exit(1). +void DeathTestImpl::Abort(AbortReason reason) { + // The parent process considers the death test to be a failure if + // it finds any data in our pipe. So, here we write a single flag byte + // to the pipe, then exit. + const char status_ch = + reason == TEST_DID_NOT_DIE ? kDeathTestLived : + reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned; + + GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1)); + // We are leaking the descriptor here because on some platforms (i.e., + // when built as Windows DLL), destructors of global objects will still + // run after calling _exit(). On such systems, write_fd_ will be + // indirectly closed from the destructor of UnitTestImpl, causing double + // close if it is also closed here. On debug configurations, double close + // may assert. As there are no in-process buffers to flush here, we are + // relying on the OS to close the descriptor after the process terminates + // when the destructors are not run. + _exit(1); // Exits w/o any normal exit hooks (we were supposed to crash) +} + +// Returns an indented copy of stderr output for a death test. +// This makes distinguishing death test output lines from regular log lines +// much easier. +static ::std::string FormatDeathTestOutput(const ::std::string& output) { + ::std::string ret; + for (size_t at = 0; ; ) { + const size_t line_end = output.find('\n', at); + ret += "[ DEATH ] "; + if (line_end == ::std::string::npos) { + ret += output.substr(at); + break; + } + ret += output.substr(at, line_end + 1 - at); + at = line_end + 1; + } + return ret; +} + +// Assesses the success or failure of a death test, using both private +// members which have previously been set, and one argument: +// +// Private data members: +// outcome: An enumeration describing how the death test +// concluded: DIED, LIVED, THREW, or RETURNED. The death test +// fails in the latter three cases. +// status: The exit status of the child process. On *nix, it is in the +// in the format specified by wait(2). On Windows, this is the +// value supplied to the ExitProcess() API or a numeric code +// of the exception that terminated the program. +// regex: A regular expression object to be applied to +// the test's captured standard error output; the death test +// fails if it does not match. +// +// Argument: +// status_ok: true if exit_status is acceptable in the context of +// this particular death test, which fails if it is false +// +// Returns true iff all of the above conditions are met. Otherwise, the +// first failing condition, in the order given above, is the one that is +// reported. Also sets the last death test message string. +bool DeathTestImpl::Passed(bool status_ok) { + if (!spawned()) + return false; + + const std::string error_message = GetCapturedStderr(); + + bool success = false; + Message buffer; + + buffer << "Death test: " << statement() << "\n"; + switch (outcome()) { + case LIVED: + buffer << " Result: failed to die.\n" + << " Error msg:\n" << FormatDeathTestOutput(error_message); + break; + case THREW: + buffer << " Result: threw an exception.\n" + << " Error msg:\n" << FormatDeathTestOutput(error_message); + break; + case RETURNED: + buffer << " Result: illegal return in test statement.\n" + << " Error msg:\n" << FormatDeathTestOutput(error_message); + break; + case DIED: + if (status_ok) { + const bool matched = RE::PartialMatch(error_message.c_str(), *regex()); + if (matched) { + success = true; + } else { + buffer << " Result: died but not with expected error.\n" + << " Expected: " << regex()->pattern() << "\n" + << "Actual msg:\n" << FormatDeathTestOutput(error_message); + } + } else { + buffer << " Result: died but not with expected exit code:\n" + << " " << ExitSummary(status()) << "\n" + << "Actual msg:\n" << FormatDeathTestOutput(error_message); + } + break; + case IN_PROGRESS: + default: + GTEST_LOG_(FATAL) + << "DeathTest::Passed somehow called before conclusion of test"; + } + + DeathTest::set_last_death_test_message(buffer.GetString()); + return success; +} + +# if GTEST_OS_WINDOWS +// WindowsDeathTest implements death tests on Windows. Due to the +// specifics of starting new processes on Windows, death tests there are +// always threadsafe, and Google Test considers the +// --gtest_death_test_style=fast setting to be equivalent to +// --gtest_death_test_style=threadsafe there. +// +// A few implementation notes: Like the Linux version, the Windows +// implementation uses pipes for child-to-parent communication. But due to +// the specifics of pipes on Windows, some extra steps are required: +// +// 1. The parent creates a communication pipe and stores handles to both +// ends of it. +// 2. The parent starts the child and provides it with the information +// necessary to acquire the handle to the write end of the pipe. +// 3. The child acquires the write end of the pipe and signals the parent +// using a Windows event. +// 4. Now the parent can release the write end of the pipe on its side. If +// this is done before step 3, the object's reference count goes down to +// 0 and it is destroyed, preventing the child from acquiring it. The +// parent now has to release it, or read operations on the read end of +// the pipe will not return when the child terminates. +// 5. The parent reads child's output through the pipe (outcome code and +// any possible error messages) from the pipe, and its stderr and then +// determines whether to fail the test. +// +// Note: to distinguish Win32 API calls from the local method and function +// calls, the former are explicitly resolved in the global namespace. +// +class WindowsDeathTest : public DeathTestImpl { + public: + WindowsDeathTest(const char* a_statement, + const RE* a_regex, + const char* file, + int line) + : DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {} + + // All of these virtual functions are inherited from DeathTest. + virtual int Wait(); + virtual TestRole AssumeRole(); + + private: + // The name of the file in which the death test is located. + const char* const file_; + // The line number on which the death test is located. + const int line_; + // Handle to the write end of the pipe to the child process. + AutoHandle write_handle_; + // Child process handle. + AutoHandle child_handle_; + // Event the child process uses to signal the parent that it has + // acquired the handle to the write end of the pipe. After seeing this + // event the parent can release its own handles to make sure its + // ReadFile() calls return when the child terminates. + AutoHandle event_handle_; +}; + +// Waits for the child in a death test to exit, returning its exit +// status, or 0 if no child process exists. As a side effect, sets the +// outcome data member. +int WindowsDeathTest::Wait() { + if (!spawned()) + return 0; + + // Wait until the child either signals that it has acquired the write end + // of the pipe or it dies. + const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() }; + switch (::WaitForMultipleObjects(2, + wait_handles, + FALSE, // Waits for any of the handles. + INFINITE)) { + case WAIT_OBJECT_0: + case WAIT_OBJECT_0 + 1: + break; + default: + GTEST_DEATH_TEST_CHECK_(false); // Should not get here. + } + + // The child has acquired the write end of the pipe or exited. + // We release the handle on our side and continue. + write_handle_.Reset(); + event_handle_.Reset(); + + ReadAndInterpretStatusByte(); + + // Waits for the child process to exit if it haven't already. This + // returns immediately if the child has already exited, regardless of + // whether previous calls to WaitForMultipleObjects synchronized on this + // handle or not. + GTEST_DEATH_TEST_CHECK_( + WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(), + INFINITE)); + DWORD status_code; + GTEST_DEATH_TEST_CHECK_( + ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE); + child_handle_.Reset(); + set_status(static_cast(status_code)); + return status(); +} + +// The AssumeRole process for a Windows death test. It creates a child +// process with the same executable as the current process to run the +// death test. The child process is given the --gtest_filter and +// --gtest_internal_run_death_test flags such that it knows to run the +// current death test only. +DeathTest::TestRole WindowsDeathTest::AssumeRole() { + const UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const TestInfo* const info = impl->current_test_info(); + const int death_test_index = info->result()->death_test_count(); + + if (flag != NULL) { + // ParseInternalRunDeathTestFlag() has performed all the necessary + // processing. + set_write_fd(flag->write_fd()); + return EXECUTE_TEST; + } + + // WindowsDeathTest uses an anonymous pipe to communicate results of + // a death test. + SECURITY_ATTRIBUTES handles_are_inheritable = { + sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; + HANDLE read_handle, write_handle; + GTEST_DEATH_TEST_CHECK_( + ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable, + 0) // Default buffer size. + != FALSE); + set_read_fd(::_open_osfhandle(reinterpret_cast(read_handle), + O_RDONLY)); + write_handle_.Reset(write_handle); + event_handle_.Reset(::CreateEvent( + &handles_are_inheritable, + TRUE, // The event will automatically reset to non-signaled state. + FALSE, // The initial state is non-signalled. + NULL)); // The even is unnamed. + GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL); + const std::string filter_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" + + info->test_case_name() + "." + info->name(); + const std::string internal_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + + "=" + file_ + "|" + StreamableToString(line_) + "|" + + StreamableToString(death_test_index) + "|" + + StreamableToString(static_cast(::GetCurrentProcessId())) + + // size_t has the same width as pointers on both 32-bit and 64-bit + // Windows platforms. + // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx. + "|" + StreamableToString(reinterpret_cast(write_handle)) + + "|" + StreamableToString(reinterpret_cast(event_handle_.Get())); + + char executable_path[_MAX_PATH + 1]; // NOLINT + GTEST_DEATH_TEST_CHECK_( + _MAX_PATH + 1 != ::GetModuleFileNameA(NULL, + executable_path, + _MAX_PATH)); + + std::string command_line = + std::string(::GetCommandLineA()) + " " + filter_flag + " \"" + + internal_flag + "\""; + + DeathTest::set_last_death_test_message(""); + + CaptureStderr(); + // Flush the log buffers since the log streams are shared with the child. + FlushInfoLog(); + + // The child process will share the standard handles with the parent. + STARTUPINFOA startup_info; + memset(&startup_info, 0, sizeof(STARTUPINFO)); + startup_info.dwFlags = STARTF_USESTDHANDLES; + startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE); + startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE); + startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE); + + PROCESS_INFORMATION process_info; + GTEST_DEATH_TEST_CHECK_(::CreateProcessA( + executable_path, + const_cast(command_line.c_str()), + NULL, // Retuned process handle is not inheritable. + NULL, // Retuned thread handle is not inheritable. + TRUE, // Child inherits all inheritable handles (for write_handle_). + 0x0, // Default creation flags. + NULL, // Inherit the parent's environment. + UnitTest::GetInstance()->original_working_dir(), + &startup_info, + &process_info) != FALSE); + child_handle_.Reset(process_info.hProcess); + ::CloseHandle(process_info.hThread); + set_spawned(true); + return OVERSEE_TEST; +} +# else // We are not on Windows. + +// ForkingDeathTest provides implementations for most of the abstract +// methods of the DeathTest interface. Only the AssumeRole method is +// left undefined. +class ForkingDeathTest : public DeathTestImpl { + public: + ForkingDeathTest(const char* statement, const RE* regex); + + // All of these virtual functions are inherited from DeathTest. + virtual int Wait(); + + protected: + void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; } + + private: + // PID of child process during death test; 0 in the child process itself. + pid_t child_pid_; +}; + +// Constructs a ForkingDeathTest. +ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex) + : DeathTestImpl(a_statement, a_regex), + child_pid_(-1) {} + +// Waits for the child in a death test to exit, returning its exit +// status, or 0 if no child process exists. As a side effect, sets the +// outcome data member. +int ForkingDeathTest::Wait() { + if (!spawned()) + return 0; + + ReadAndInterpretStatusByte(); + + int status_value; + GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0)); + set_status(status_value); + return status_value; +} + +// A concrete death test class that forks, then immediately runs the test +// in the child process. +class NoExecDeathTest : public ForkingDeathTest { + public: + NoExecDeathTest(const char* a_statement, const RE* a_regex) : + ForkingDeathTest(a_statement, a_regex) { } + virtual TestRole AssumeRole(); +}; + +// The AssumeRole process for a fork-and-run death test. It implements a +// straightforward fork, with a simple pipe to transmit the status byte. +DeathTest::TestRole NoExecDeathTest::AssumeRole() { + const size_t thread_count = GetThreadCount(); + if (thread_count != 1) { + GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count); + } + + int pipe_fd[2]; + GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1); + + DeathTest::set_last_death_test_message(""); + CaptureStderr(); + // When we fork the process below, the log file buffers are copied, but the + // file descriptors are shared. We flush all log files here so that closing + // the file descriptors in the child process doesn't throw off the + // synchronization between descriptors and buffers in the parent process. + // This is as close to the fork as possible to avoid a race condition in case + // there are multiple threads running before the death test, and another + // thread writes to the log file. + FlushInfoLog(); + + const pid_t child_pid = fork(); + GTEST_DEATH_TEST_CHECK_(child_pid != -1); + set_child_pid(child_pid); + if (child_pid == 0) { + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[0])); + set_write_fd(pipe_fd[1]); + // Redirects all logging to stderr in the child process to prevent + // concurrent writes to the log files. We capture stderr in the parent + // process and append the child process' output to a log. + LogToStderr(); + // Event forwarding to the listeners of event listener API mush be shut + // down in death test subprocesses. + GetUnitTestImpl()->listeners()->SuppressEventForwarding(); + g_in_fast_death_test_child = true; + return EXECUTE_TEST; + } else { + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); + set_read_fd(pipe_fd[0]); + set_spawned(true); + return OVERSEE_TEST; + } +} + +// A concrete death test class that forks and re-executes the main +// program from the beginning, with command-line flags set that cause +// only this specific death test to be run. +class ExecDeathTest : public ForkingDeathTest { + public: + ExecDeathTest(const char* a_statement, const RE* a_regex, + const char* file, int line) : + ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { } + virtual TestRole AssumeRole(); + private: + static ::std::vector + GetArgvsForDeathTestChildProcess() { + ::std::vector args = GetInjectableArgvs(); + return args; + } + // The name of the file in which the death test is located. + const char* const file_; + // The line number on which the death test is located. + const int line_; +}; + +// Utility class for accumulating command-line arguments. +class Arguments { + public: + Arguments() { + args_.push_back(NULL); + } + + ~Arguments() { + for (std::vector::iterator i = args_.begin(); i != args_.end(); + ++i) { + free(*i); + } + } + void AddArgument(const char* argument) { + args_.insert(args_.end() - 1, posix::StrDup(argument)); + } + + template + void AddArguments(const ::std::vector& arguments) { + for (typename ::std::vector::const_iterator i = arguments.begin(); + i != arguments.end(); + ++i) { + args_.insert(args_.end() - 1, posix::StrDup(i->c_str())); + } + } + char* const* Argv() { + return &args_[0]; + } + + private: + std::vector args_; +}; + +// A struct that encompasses the arguments to the child process of a +// threadsafe-style death test process. +struct ExecDeathTestArgs { + char* const* argv; // Command-line arguments for the child's call to exec + int close_fd; // File descriptor to close; the read end of a pipe +}; + +# if GTEST_OS_MAC +inline char** GetEnviron() { + // When Google Test is built as a framework on MacOS X, the environ variable + // is unavailable. Apple's documentation (man environ) recommends using + // _NSGetEnviron() instead. + return *_NSGetEnviron(); +} +# else +// Some POSIX platforms expect you to declare environ. extern "C" makes +// it reside in the global namespace. +extern "C" char** environ; +inline char** GetEnviron() { return environ; } +# endif // GTEST_OS_MAC + +# if !GTEST_OS_QNX +// The main function for a threadsafe-style death test child process. +// This function is called in a clone()-ed process and thus must avoid +// any potentially unsafe operations like malloc or libc functions. +static int ExecDeathTestChildMain(void* child_arg) { + ExecDeathTestArgs* const args = static_cast(child_arg); + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd)); + + // We need to execute the test program in the same environment where + // it was originally invoked. Therefore we change to the original + // working directory first. + const char* const original_dir = + UnitTest::GetInstance()->original_working_dir(); + // We can safely call chdir() as it's a direct system call. + if (chdir(original_dir) != 0) { + DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " + + GetLastErrnoDescription()); + return EXIT_FAILURE; + } + + // We can safely call execve() as it's a direct system call. We + // cannot use execvp() as it's a libc function and thus potentially + // unsafe. Since execve() doesn't search the PATH, the user must + // invoke the test program via a valid path that contains at least + // one path separator. + execve(args->argv[0], args->argv, GetEnviron()); + DeathTestAbort(std::string("execve(") + args->argv[0] + ", ...) in " + + original_dir + " failed: " + + GetLastErrnoDescription()); + return EXIT_FAILURE; +} +# endif // !GTEST_OS_QNX + +// Two utility routines that together determine the direction the stack +// grows. +// This could be accomplished more elegantly by a single recursive +// function, but we want to guard against the unlikely possibility of +// a smart compiler optimizing the recursion away. +// +// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining +// StackLowerThanAddress into StackGrowsDown, which then doesn't give +// correct answer. +void StackLowerThanAddress(const void* ptr, bool* result) GTEST_NO_INLINE_; +void StackLowerThanAddress(const void* ptr, bool* result) { + int dummy; + *result = (&dummy < ptr); +} + +bool StackGrowsDown() { + int dummy; + bool result; + StackLowerThanAddress(&dummy, &result); + return result; +} + +// Spawns a child process with the same executable as the current process in +// a thread-safe manner and instructs it to run the death test. The +// implementation uses fork(2) + exec. On systems where clone(2) is +// available, it is used instead, being slightly more thread-safe. On QNX, +// fork supports only single-threaded environments, so this function uses +// spawn(2) there instead. The function dies with an error message if +// anything goes wrong. +static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) { + ExecDeathTestArgs args = { argv, close_fd }; + pid_t child_pid = -1; + +# if GTEST_OS_QNX + // Obtains the current directory and sets it to be closed in the child + // process. + const int cwd_fd = open(".", O_RDONLY); + GTEST_DEATH_TEST_CHECK_(cwd_fd != -1); + GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC)); + // We need to execute the test program in the same environment where + // it was originally invoked. Therefore we change to the original + // working directory first. + const char* const original_dir = + UnitTest::GetInstance()->original_working_dir(); + // We can safely call chdir() as it's a direct system call. + if (chdir(original_dir) != 0) { + DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " + + GetLastErrnoDescription()); + return EXIT_FAILURE; + } + + int fd_flags; + // Set close_fd to be closed after spawn. + GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD)); + GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(close_fd, F_SETFD, + fd_flags | FD_CLOEXEC)); + struct inheritance inherit = {0}; + // spawn is a system call. + child_pid = spawn(args.argv[0], 0, NULL, &inherit, args.argv, GetEnviron()); + // Restores the current working directory. + GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1); + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd)); + +# else // GTEST_OS_QNX +# if GTEST_OS_LINUX + // When a SIGPROF signal is received while fork() or clone() are executing, + // the process may hang. To avoid this, we ignore SIGPROF here and re-enable + // it after the call to fork()/clone() is complete. + struct sigaction saved_sigprof_action; + struct sigaction ignore_sigprof_action; + memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action)); + sigemptyset(&ignore_sigprof_action.sa_mask); + ignore_sigprof_action.sa_handler = SIG_IGN; + GTEST_DEATH_TEST_CHECK_SYSCALL_(sigaction( + SIGPROF, &ignore_sigprof_action, &saved_sigprof_action)); +# endif // GTEST_OS_LINUX + +# if GTEST_HAS_CLONE + const bool use_fork = GTEST_FLAG(death_test_use_fork); + + if (!use_fork) { + static const bool stack_grows_down = StackGrowsDown(); + const size_t stack_size = getpagesize(); + // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead. + void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, -1, 0); + GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED); + + // Maximum stack alignment in bytes: For a downward-growing stack, this + // amount is subtracted from size of the stack space to get an address + // that is within the stack space and is aligned on all systems we care + // about. As far as I know there is no ABI with stack alignment greater + // than 64. We assume stack and stack_size already have alignment of + // kMaxStackAlignment. + const size_t kMaxStackAlignment = 64; + void* const stack_top = + static_cast(stack) + + (stack_grows_down ? stack_size - kMaxStackAlignment : 0); + GTEST_DEATH_TEST_CHECK_(stack_size > kMaxStackAlignment && + reinterpret_cast(stack_top) % kMaxStackAlignment == 0); + + child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args); + + GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1); + } +# else + const bool use_fork = true; +# endif // GTEST_HAS_CLONE + + if (use_fork && (child_pid = fork()) == 0) { + ExecDeathTestChildMain(&args); + _exit(0); + } +# endif // GTEST_OS_QNX +# if GTEST_OS_LINUX + GTEST_DEATH_TEST_CHECK_SYSCALL_( + sigaction(SIGPROF, &saved_sigprof_action, NULL)); +# endif // GTEST_OS_LINUX + + GTEST_DEATH_TEST_CHECK_(child_pid != -1); + return child_pid; +} + +// The AssumeRole process for a fork-and-exec death test. It re-executes the +// main program from the beginning, setting the --gtest_filter +// and --gtest_internal_run_death_test flags to cause only the current +// death test to be re-run. +DeathTest::TestRole ExecDeathTest::AssumeRole() { + const UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const TestInfo* const info = impl->current_test_info(); + const int death_test_index = info->result()->death_test_count(); + + if (flag != NULL) { + set_write_fd(flag->write_fd()); + return EXECUTE_TEST; + } + + int pipe_fd[2]; + GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1); + // Clear the close-on-exec flag on the write end of the pipe, lest + // it be closed when the child process does an exec: + GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1); + + const std::string filter_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" + + info->test_case_name() + "." + info->name(); + const std::string internal_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "=" + + file_ + "|" + StreamableToString(line_) + "|" + + StreamableToString(death_test_index) + "|" + + StreamableToString(pipe_fd[1]); + Arguments args; + args.AddArguments(GetArgvsForDeathTestChildProcess()); + args.AddArgument(filter_flag.c_str()); + args.AddArgument(internal_flag.c_str()); + + DeathTest::set_last_death_test_message(""); + + CaptureStderr(); + // See the comment in NoExecDeathTest::AssumeRole for why the next line + // is necessary. + FlushInfoLog(); + + const pid_t child_pid = ExecDeathTestSpawnChild(args.Argv(), pipe_fd[0]); + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); + set_child_pid(child_pid); + set_read_fd(pipe_fd[0]); + set_spawned(true); + return OVERSEE_TEST; +} + +# endif // !GTEST_OS_WINDOWS + +// Creates a concrete DeathTest-derived class that depends on the +// --gtest_death_test_style flag, and sets the pointer pointed to +// by the "test" argument to its address. If the test should be +// skipped, sets that pointer to NULL. Returns true, unless the +// flag is set to an invalid value. +bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, + const char* file, int line, + DeathTest** test) { + UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const int death_test_index = impl->current_test_info() + ->increment_death_test_count(); + + if (flag != NULL) { + if (death_test_index > flag->index()) { + DeathTest::set_last_death_test_message( + "Death test count (" + StreamableToString(death_test_index) + + ") somehow exceeded expected maximum (" + + StreamableToString(flag->index()) + ")"); + return false; + } + + if (!(flag->file() == file && flag->line() == line && + flag->index() == death_test_index)) { + *test = NULL; + return true; + } + } + +# if GTEST_OS_WINDOWS + + if (GTEST_FLAG(death_test_style) == "threadsafe" || + GTEST_FLAG(death_test_style) == "fast") { + *test = new WindowsDeathTest(statement, regex, file, line); + } + +# else + + if (GTEST_FLAG(death_test_style) == "threadsafe") { + *test = new ExecDeathTest(statement, regex, file, line); + } else if (GTEST_FLAG(death_test_style) == "fast") { + *test = new NoExecDeathTest(statement, regex); + } + +# endif // GTEST_OS_WINDOWS + + else { // NOLINT - this is more readable than unbalanced brackets inside #if. + DeathTest::set_last_death_test_message( + "Unknown death test style \"" + GTEST_FLAG(death_test_style) + + "\" encountered"); + return false; + } + + return true; +} + +// Splits a given string on a given delimiter, populating a given +// vector with the fields. GTEST_HAS_DEATH_TEST implies that we have +// ::std::string, so we can use it here. +static void SplitString(const ::std::string& str, char delimiter, + ::std::vector< ::std::string>* dest) { + ::std::vector< ::std::string> parsed; + ::std::string::size_type pos = 0; + while (::testing::internal::AlwaysTrue()) { + const ::std::string::size_type colon = str.find(delimiter, pos); + if (colon == ::std::string::npos) { + parsed.push_back(str.substr(pos)); + break; + } else { + parsed.push_back(str.substr(pos, colon - pos)); + pos = colon + 1; + } + } + dest->swap(parsed); +} + +# if GTEST_OS_WINDOWS +// Recreates the pipe and event handles from the provided parameters, +// signals the event, and returns a file descriptor wrapped around the pipe +// handle. This function is called in the child process only. +int GetStatusFileDescriptor(unsigned int parent_process_id, + size_t write_handle_as_size_t, + size_t event_handle_as_size_t) { + AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE, + FALSE, // Non-inheritable. + parent_process_id)); + if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) { + DeathTestAbort("Unable to open parent process " + + StreamableToString(parent_process_id)); + } + + // TODO(vladl@google.com): Replace the following check with a + // compile-time assertion when available. + GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t)); + + const HANDLE write_handle = + reinterpret_cast(write_handle_as_size_t); + HANDLE dup_write_handle; + + // The newly initialized handle is accessible only in in the parent + // process. To obtain one accessible within the child, we need to use + // DuplicateHandle. + if (!::DuplicateHandle(parent_process_handle.Get(), write_handle, + ::GetCurrentProcess(), &dup_write_handle, + 0x0, // Requested privileges ignored since + // DUPLICATE_SAME_ACCESS is used. + FALSE, // Request non-inheritable handler. + DUPLICATE_SAME_ACCESS)) { + DeathTestAbort("Unable to duplicate the pipe handle " + + StreamableToString(write_handle_as_size_t) + + " from the parent process " + + StreamableToString(parent_process_id)); + } + + const HANDLE event_handle = reinterpret_cast(event_handle_as_size_t); + HANDLE dup_event_handle; + + if (!::DuplicateHandle(parent_process_handle.Get(), event_handle, + ::GetCurrentProcess(), &dup_event_handle, + 0x0, + FALSE, + DUPLICATE_SAME_ACCESS)) { + DeathTestAbort("Unable to duplicate the event handle " + + StreamableToString(event_handle_as_size_t) + + " from the parent process " + + StreamableToString(parent_process_id)); + } + + const int write_fd = + ::_open_osfhandle(reinterpret_cast(dup_write_handle), O_APPEND); + if (write_fd == -1) { + DeathTestAbort("Unable to convert pipe handle " + + StreamableToString(write_handle_as_size_t) + + " to a file descriptor"); + } + + // Signals the parent that the write end of the pipe has been acquired + // so the parent can release its own write end. + ::SetEvent(dup_event_handle); + + return write_fd; +} +# endif // GTEST_OS_WINDOWS + +// Returns a newly created InternalRunDeathTestFlag object with fields +// initialized from the GTEST_FLAG(internal_run_death_test) flag if +// the flag is specified; otherwise returns NULL. +InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() { + if (GTEST_FLAG(internal_run_death_test) == "") return NULL; + + // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we + // can use it here. + int line = -1; + int index = -1; + ::std::vector< ::std::string> fields; + SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields); + int write_fd = -1; + +# if GTEST_OS_WINDOWS + + unsigned int parent_process_id = 0; + size_t write_handle_as_size_t = 0; + size_t event_handle_as_size_t = 0; + + if (fields.size() != 6 + || !ParseNaturalNumber(fields[1], &line) + || !ParseNaturalNumber(fields[2], &index) + || !ParseNaturalNumber(fields[3], &parent_process_id) + || !ParseNaturalNumber(fields[4], &write_handle_as_size_t) + || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) { + DeathTestAbort("Bad --gtest_internal_run_death_test flag: " + + GTEST_FLAG(internal_run_death_test)); + } + write_fd = GetStatusFileDescriptor(parent_process_id, + write_handle_as_size_t, + event_handle_as_size_t); +# else + + if (fields.size() != 4 + || !ParseNaturalNumber(fields[1], &line) + || !ParseNaturalNumber(fields[2], &index) + || !ParseNaturalNumber(fields[3], &write_fd)) { + DeathTestAbort("Bad --gtest_internal_run_death_test flag: " + + GTEST_FLAG(internal_run_death_test)); + } + +# endif // GTEST_OS_WINDOWS + + return new InternalRunDeathTestFlag(fields[0], line, index, write_fd); +} + +} // namespace internal + +#endif // GTEST_HAS_DEATH_TEST + +} // namespace testing +// Copyright 2008, 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. +// +// Authors: keith.ray@gmail.com (Keith Ray) + + +#include + +#if GTEST_OS_WINDOWS_MOBILE +# include +#elif GTEST_OS_WINDOWS +# include +# include +#elif GTEST_OS_SYMBIAN +// Symbian OpenC has PATH_MAX in sys/syslimits.h +# include +#else +# include +# include // Some Linux distributions define PATH_MAX here. +#endif // GTEST_OS_WINDOWS_MOBILE + +#if GTEST_OS_WINDOWS +# define GTEST_PATH_MAX_ _MAX_PATH +#elif defined(PATH_MAX) +# define GTEST_PATH_MAX_ PATH_MAX +#elif defined(_XOPEN_PATH_MAX) +# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX +#else +# define GTEST_PATH_MAX_ _POSIX_PATH_MAX +#endif // GTEST_OS_WINDOWS + + +namespace testing { +namespace internal { + +#if GTEST_OS_WINDOWS +// On Windows, '\\' is the standard path separator, but many tools and the +// Windows API also accept '/' as an alternate path separator. Unless otherwise +// noted, a file path can contain either kind of path separators, or a mixture +// of them. +const char kPathSeparator = '\\'; +const char kAlternatePathSeparator = '/'; +const char kPathSeparatorString[] = "\\"; +const char kAlternatePathSeparatorString[] = "/"; +# if GTEST_OS_WINDOWS_MOBILE +// Windows CE doesn't have a current directory. You should not use +// the current directory in tests on Windows CE, but this at least +// provides a reasonable fallback. +const char kCurrentDirectoryString[] = "\\"; +// Windows CE doesn't define INVALID_FILE_ATTRIBUTES +const DWORD kInvalidFileAttributes = 0xffffffff; +# else +const char kCurrentDirectoryString[] = ".\\"; +# endif // GTEST_OS_WINDOWS_MOBILE +#else +const char kPathSeparator = '/'; +const char kPathSeparatorString[] = "/"; +const char kCurrentDirectoryString[] = "./"; +#endif // GTEST_OS_WINDOWS + +// Returns whether the given character is a valid path separator. +static bool IsPathSeparator(char c) { +#if GTEST_HAS_ALT_PATH_SEP_ + return (c == kPathSeparator) || (c == kAlternatePathSeparator); +#else + return c == kPathSeparator; +#endif +} + +// Returns the current working directory, or "" if unsuccessful. +FilePath FilePath::GetCurrentDir() { +#if GTEST_OS_WINDOWS_MOBILE + // Windows CE doesn't have a current directory, so we just return + // something reasonable. + return FilePath(kCurrentDirectoryString); +#elif GTEST_OS_WINDOWS + char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; + return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); +#else + char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; + return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); +#endif // GTEST_OS_WINDOWS_MOBILE +} + +// Returns a copy of the FilePath with the case-insensitive extension removed. +// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns +// FilePath("dir/file"). If a case-insensitive extension is not +// found, returns a copy of the original FilePath. +FilePath FilePath::RemoveExtension(const char* extension) const { + const std::string dot_extension = std::string(".") + extension; + if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) { + return FilePath(pathname_.substr( + 0, pathname_.length() - dot_extension.length())); + } + return *this; +} + +// Returns a pointer to the last occurence of a valid path separator in +// the FilePath. On Windows, for example, both '/' and '\' are valid path +// separators. Returns NULL if no path separator was found. +const char* FilePath::FindLastPathSeparator() const { + const char* const last_sep = strrchr(c_str(), kPathSeparator); +#if GTEST_HAS_ALT_PATH_SEP_ + const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator); + // Comparing two pointers of which only one is NULL is undefined. + if (last_alt_sep != NULL && + (last_sep == NULL || last_alt_sep > last_sep)) { + return last_alt_sep; + } +#endif + return last_sep; +} + +// Returns a copy of the FilePath with the directory part removed. +// Example: FilePath("path/to/file").RemoveDirectoryName() returns +// FilePath("file"). If there is no directory part ("just_a_file"), it returns +// the FilePath unmodified. If there is no file part ("just_a_dir/") it +// returns an empty FilePath (""). +// On Windows platform, '\' is the path separator, otherwise it is '/'. +FilePath FilePath::RemoveDirectoryName() const { + const char* const last_sep = FindLastPathSeparator(); + return last_sep ? FilePath(last_sep + 1) : *this; +} + +// RemoveFileName returns the directory path with the filename removed. +// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". +// If the FilePath is "a_file" or "/a_file", RemoveFileName returns +// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does +// not have a file, like "just/a/dir/", it returns the FilePath unmodified. +// On Windows platform, '\' is the path separator, otherwise it is '/'. +FilePath FilePath::RemoveFileName() const { + const char* const last_sep = FindLastPathSeparator(); + std::string dir; + if (last_sep) { + dir = std::string(c_str(), last_sep + 1 - c_str()); + } else { + dir = kCurrentDirectoryString; + } + return FilePath(dir); +} + +// Helper functions for naming files in a directory for xml output. + +// Given directory = "dir", base_name = "test", number = 0, +// extension = "xml", returns "dir/test.xml". If number is greater +// than zero (e.g., 12), returns "dir/test_12.xml". +// On Windows platform, uses \ as the separator rather than /. +FilePath FilePath::MakeFileName(const FilePath& directory, + const FilePath& base_name, + int number, + const char* extension) { + std::string file; + if (number == 0) { + file = base_name.string() + "." + extension; + } else { + file = base_name.string() + "_" + StreamableToString(number) + + "." + extension; + } + return ConcatPaths(directory, FilePath(file)); +} + +// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml". +// On Windows, uses \ as the separator rather than /. +FilePath FilePath::ConcatPaths(const FilePath& directory, + const FilePath& relative_path) { + if (directory.IsEmpty()) + return relative_path; + const FilePath dir(directory.RemoveTrailingPathSeparator()); + return FilePath(dir.string() + kPathSeparator + relative_path.string()); +} + +// Returns true if pathname describes something findable in the file-system, +// either a file, directory, or whatever. +bool FilePath::FileOrDirectoryExists() const { +#if GTEST_OS_WINDOWS_MOBILE + LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str()); + const DWORD attributes = GetFileAttributes(unicode); + delete [] unicode; + return attributes != kInvalidFileAttributes; +#else + posix::StatStruct file_stat; + return posix::Stat(pathname_.c_str(), &file_stat) == 0; +#endif // GTEST_OS_WINDOWS_MOBILE +} + +// Returns true if pathname describes a directory in the file-system +// that exists. +bool FilePath::DirectoryExists() const { + bool result = false; +#if GTEST_OS_WINDOWS + // Don't strip off trailing separator if path is a root directory on + // Windows (like "C:\\"). + const FilePath& path(IsRootDirectory() ? *this : + RemoveTrailingPathSeparator()); +#else + const FilePath& path(*this); +#endif + +#if GTEST_OS_WINDOWS_MOBILE + LPCWSTR unicode = String::AnsiToUtf16(path.c_str()); + const DWORD attributes = GetFileAttributes(unicode); + delete [] unicode; + if ((attributes != kInvalidFileAttributes) && + (attributes & FILE_ATTRIBUTE_DIRECTORY)) { + result = true; + } +#else + posix::StatStruct file_stat; + result = posix::Stat(path.c_str(), &file_stat) == 0 && + posix::IsDir(file_stat); +#endif // GTEST_OS_WINDOWS_MOBILE + + return result; +} + +// Returns true if pathname describes a root directory. (Windows has one +// root directory per disk drive.) +bool FilePath::IsRootDirectory() const { +#if GTEST_OS_WINDOWS + // TODO(wan@google.com): on Windows a network share like + // \\server\share can be a root directory, although it cannot be the + // current directory. Handle this properly. + return pathname_.length() == 3 && IsAbsolutePath(); +#else + return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]); +#endif +} + +// Returns true if pathname describes an absolute path. +bool FilePath::IsAbsolutePath() const { + const char* const name = pathname_.c_str(); +#if GTEST_OS_WINDOWS + return pathname_.length() >= 3 && + ((name[0] >= 'a' && name[0] <= 'z') || + (name[0] >= 'A' && name[0] <= 'Z')) && + name[1] == ':' && + IsPathSeparator(name[2]); +#else + return IsPathSeparator(name[0]); +#endif +} + +// Returns a pathname for a file that does not currently exist. The pathname +// will be directory/base_name.extension or +// directory/base_name_.extension if directory/base_name.extension +// already exists. The number will be incremented until a pathname is found +// that does not already exist. +// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. +// There could be a race condition if two or more processes are calling this +// function at the same time -- they could both pick the same filename. +FilePath FilePath::GenerateUniqueFileName(const FilePath& directory, + const FilePath& base_name, + const char* extension) { + FilePath full_pathname; + int number = 0; + do { + full_pathname.Set(MakeFileName(directory, base_name, number++, extension)); + } while (full_pathname.FileOrDirectoryExists()); + return full_pathname; +} + +// Returns true if FilePath ends with a path separator, which indicates that +// it is intended to represent a directory. Returns false otherwise. +// This does NOT check that a directory (or file) actually exists. +bool FilePath::IsDirectory() const { + return !pathname_.empty() && + IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]); +} + +// Create directories so that path exists. Returns true if successful or if +// the directories already exist; returns false if unable to create directories +// for any reason. +bool FilePath::CreateDirectoriesRecursively() const { + if (!this->IsDirectory()) { + return false; + } + + if (pathname_.length() == 0 || this->DirectoryExists()) { + return true; + } + + const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName()); + return parent.CreateDirectoriesRecursively() && this->CreateFolder(); +} + +// Create the directory so that path exists. Returns true if successful or +// if the directory already exists; returns false if unable to create the +// directory for any reason, including if the parent directory does not +// exist. Not named "CreateDirectory" because that's a macro on Windows. +bool FilePath::CreateFolder() const { +#if GTEST_OS_WINDOWS_MOBILE + FilePath removed_sep(this->RemoveTrailingPathSeparator()); + LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str()); + int result = CreateDirectory(unicode, NULL) ? 0 : -1; + delete [] unicode; +#elif GTEST_OS_WINDOWS + int result = _mkdir(pathname_.c_str()); +#else + int result = mkdir(pathname_.c_str(), 0777); +#endif // GTEST_OS_WINDOWS_MOBILE + + if (result == -1) { + return this->DirectoryExists(); // An error is OK if the directory exists. + } + return true; // No error. +} + +// If input name has a trailing separator character, remove it and return the +// name, otherwise return the name string unmodified. +// On Windows platform, uses \ as the separator, other platforms use /. +FilePath FilePath::RemoveTrailingPathSeparator() const { + return IsDirectory() + ? FilePath(pathname_.substr(0, pathname_.length() - 1)) + : *this; +} + +// Removes any redundant separators that might be in the pathname. +// For example, "bar///foo" becomes "bar/foo". Does not eliminate other +// redundancies that might be in a pathname involving "." or "..". +// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share). +void FilePath::Normalize() { + if (pathname_.c_str() == NULL) { + pathname_ = ""; + return; + } + const char* src = pathname_.c_str(); + char* const dest = new char[pathname_.length() + 1]; + char* dest_ptr = dest; + memset(dest_ptr, 0, pathname_.length() + 1); + + while (*src != '\0') { + *dest_ptr = *src; + if (!IsPathSeparator(*src)) { + src++; + } else { +#if GTEST_HAS_ALT_PATH_SEP_ + if (*dest_ptr == kAlternatePathSeparator) { + *dest_ptr = kPathSeparator; + } +#endif + while (IsPathSeparator(*src)) + src++; + } + dest_ptr++; + } + *dest_ptr = '\0'; + pathname_ = dest; + delete[] dest; +} + +} // namespace internal +} // namespace testing +// Copyright 2008, 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 +#include +#include +#include + +#if GTEST_OS_WINDOWS_MOBILE +# include // For TerminateProcess() +#elif GTEST_OS_WINDOWS +# include +# include +#else +# include +#endif // GTEST_OS_WINDOWS_MOBILE + +#if GTEST_OS_MAC +# include +# include +# include +#endif // GTEST_OS_MAC + +#if GTEST_OS_QNX +# include +# include +#endif // GTEST_OS_QNX + + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +#undef GTEST_IMPLEMENTATION_ + +namespace testing { +namespace internal { + +#if defined(_MSC_VER) || defined(__BORLANDC__) +// MSVC and C++Builder do not provide a definition of STDERR_FILENO. +const int kStdOutFileno = 1; +const int kStdErrFileno = 2; +#else +const int kStdOutFileno = STDOUT_FILENO; +const int kStdErrFileno = STDERR_FILENO; +#endif // _MSC_VER + +#if GTEST_OS_MAC + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +size_t GetThreadCount() { + const task_t task = mach_task_self(); + mach_msg_type_number_t thread_count; + thread_act_array_t thread_list; + const kern_return_t status = task_threads(task, &thread_list, &thread_count); + if (status == KERN_SUCCESS) { + // task_threads allocates resources in thread_list and we need to free them + // to avoid leaks. + vm_deallocate(task, + reinterpret_cast(thread_list), + sizeof(thread_t) * thread_count); + return static_cast(thread_count); + } else { + return 0; + } +} + +#elif GTEST_OS_QNX + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +size_t GetThreadCount() { + const int fd = open("/proc/self/as", O_RDONLY); + if (fd < 0) { + return 0; + } + procfs_info process_info; + const int status = + devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), NULL); + close(fd); + if (status == EOK) { + return static_cast(process_info.num_threads); + } else { + return 0; + } +} + +#else + +size_t GetThreadCount() { + // There's no portable way to detect the number of threads, so we just + // return 0 to indicate that we cannot detect it. + return 0; +} + +#endif // GTEST_OS_MAC + +#if GTEST_USES_POSIX_RE + +// Implements RE. Currently only needed for death tests. + +RE::~RE() { + if (is_valid_) { + // regfree'ing an invalid regex might crash because the content + // of the regex is undefined. Since the regex's are essentially + // the same, one cannot be valid (or invalid) without the other + // being so too. + regfree(&partial_regex_); + regfree(&full_regex_); + } + free(const_cast(pattern_)); +} + +// Returns true iff regular expression re matches the entire str. +bool RE::FullMatch(const char* str, const RE& re) { + if (!re.is_valid_) return false; + + regmatch_t match; + return regexec(&re.full_regex_, str, 1, &match, 0) == 0; +} + +// Returns true iff regular expression re matches a substring of str +// (including str itself). +bool RE::PartialMatch(const char* str, const RE& re) { + if (!re.is_valid_) return false; + + regmatch_t match; + return regexec(&re.partial_regex_, str, 1, &match, 0) == 0; +} + +// Initializes an RE from its string representation. +void RE::Init(const char* regex) { + pattern_ = posix::StrDup(regex); + + // Reserves enough bytes to hold the regular expression used for a + // full match. + const size_t full_regex_len = strlen(regex) + 10; + char* const full_pattern = new char[full_regex_len]; + + snprintf(full_pattern, full_regex_len, "^(%s)$", regex); + is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0; + // We want to call regcomp(&partial_regex_, ...) even if the + // previous expression returns false. Otherwise partial_regex_ may + // not be properly initialized can may cause trouble when it's + // freed. + // + // Some implementation of POSIX regex (e.g. on at least some + // versions of Cygwin) doesn't accept the empty string as a valid + // regex. We change it to an equivalent form "()" to be safe. + if (is_valid_) { + const char* const partial_regex = (*regex == '\0') ? "()" : regex; + is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0; + } + EXPECT_TRUE(is_valid_) + << "Regular expression \"" << regex + << "\" is not a valid POSIX Extended regular expression."; + + delete[] full_pattern; +} + +#elif GTEST_USES_SIMPLE_RE + +// Returns true iff ch appears anywhere in str (excluding the +// terminating '\0' character). +bool IsInSet(char ch, const char* str) { + return ch != '\0' && strchr(str, ch) != NULL; +} + +// Returns true iff ch belongs to the given classification. Unlike +// similar functions in , these aren't affected by the +// current locale. +bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; } +bool IsAsciiPunct(char ch) { + return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~"); +} +bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); } +bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); } +bool IsAsciiWordChar(char ch) { + return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || + ('0' <= ch && ch <= '9') || ch == '_'; +} + +// Returns true iff "\\c" is a supported escape sequence. +bool IsValidEscape(char c) { + return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW")); +} + +// Returns true iff the given atom (specified by escaped and pattern) +// matches ch. The result is undefined if the atom is invalid. +bool AtomMatchesChar(bool escaped, char pattern_char, char ch) { + if (escaped) { // "\\p" where p is pattern_char. + switch (pattern_char) { + case 'd': return IsAsciiDigit(ch); + case 'D': return !IsAsciiDigit(ch); + case 'f': return ch == '\f'; + case 'n': return ch == '\n'; + case 'r': return ch == '\r'; + case 's': return IsAsciiWhiteSpace(ch); + case 'S': return !IsAsciiWhiteSpace(ch); + case 't': return ch == '\t'; + case 'v': return ch == '\v'; + case 'w': return IsAsciiWordChar(ch); + case 'W': return !IsAsciiWordChar(ch); + } + return IsAsciiPunct(pattern_char) && pattern_char == ch; + } + + return (pattern_char == '.' && ch != '\n') || pattern_char == ch; +} + +// Helper function used by ValidateRegex() to format error messages. +std::string FormatRegexSyntaxError(const char* regex, int index) { + return (Message() << "Syntax error at index " << index + << " in simple regular expression \"" << regex << "\": ").GetString(); +} + +// Generates non-fatal failures and returns false if regex is invalid; +// otherwise returns true. +bool ValidateRegex(const char* regex) { + if (regex == NULL) { + // TODO(wan@google.com): fix the source file location in the + // assertion failures to match where the regex is used in user + // code. + ADD_FAILURE() << "NULL is not a valid simple regular expression."; + return false; + } + + bool is_valid = true; + + // True iff ?, *, or + can follow the previous atom. + bool prev_repeatable = false; + for (int i = 0; regex[i]; i++) { + if (regex[i] == '\\') { // An escape sequence + i++; + if (regex[i] == '\0') { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) + << "'\\' cannot appear at the end."; + return false; + } + + if (!IsValidEscape(regex[i])) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) + << "invalid escape sequence \"\\" << regex[i] << "\"."; + is_valid = false; + } + prev_repeatable = true; + } else { // Not an escape sequence. + const char ch = regex[i]; + + if (ch == '^' && i > 0) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'^' can only appear at the beginning."; + is_valid = false; + } else if (ch == '$' && regex[i + 1] != '\0') { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'$' can only appear at the end."; + is_valid = false; + } else if (IsInSet(ch, "()[]{}|")) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'" << ch << "' is unsupported."; + is_valid = false; + } else if (IsRepeat(ch) && !prev_repeatable) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'" << ch << "' can only follow a repeatable token."; + is_valid = false; + } + + prev_repeatable = !IsInSet(ch, "^$?*+"); + } + } + + return is_valid; +} + +// Matches a repeated regex atom followed by a valid simple regular +// expression. The regex atom is defined as c if escaped is false, +// or \c otherwise. repeat is the repetition meta character (?, *, +// or +). The behavior is undefined if str contains too many +// characters to be indexable by size_t, in which case the test will +// probably time out anyway. We are fine with this limitation as +// std::string has it too. +bool MatchRepetitionAndRegexAtHead( + bool escaped, char c, char repeat, const char* regex, + const char* str) { + const size_t min_count = (repeat == '+') ? 1 : 0; + const size_t max_count = (repeat == '?') ? 1 : + static_cast(-1) - 1; + // We cannot call numeric_limits::max() as it conflicts with the + // max() macro on Windows. + + for (size_t i = 0; i <= max_count; ++i) { + // We know that the atom matches each of the first i characters in str. + if (i >= min_count && MatchRegexAtHead(regex, str + i)) { + // We have enough matches at the head, and the tail matches too. + // Since we only care about *whether* the pattern matches str + // (as opposed to *how* it matches), there is no need to find a + // greedy match. + return true; + } + if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i])) + return false; + } + return false; +} + +// Returns true iff regex matches a prefix of str. regex must be a +// valid simple regular expression and not start with "^", or the +// result is undefined. +bool MatchRegexAtHead(const char* regex, const char* str) { + if (*regex == '\0') // An empty regex matches a prefix of anything. + return true; + + // "$" only matches the end of a string. Note that regex being + // valid guarantees that there's nothing after "$" in it. + if (*regex == '$') + return *str == '\0'; + + // Is the first thing in regex an escape sequence? + const bool escaped = *regex == '\\'; + if (escaped) + ++regex; + if (IsRepeat(regex[1])) { + // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so + // here's an indirect recursion. It terminates as the regex gets + // shorter in each recursion. + return MatchRepetitionAndRegexAtHead( + escaped, regex[0], regex[1], regex + 2, str); + } else { + // regex isn't empty, isn't "$", and doesn't start with a + // repetition. We match the first atom of regex with the first + // character of str and recurse. + return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) && + MatchRegexAtHead(regex + 1, str + 1); + } +} + +// Returns true iff regex matches any substring of str. regex must be +// a valid simple regular expression, or the result is undefined. +// +// The algorithm is recursive, but the recursion depth doesn't exceed +// the regex length, so we won't need to worry about running out of +// stack space normally. In rare cases the time complexity can be +// exponential with respect to the regex length + the string length, +// but usually it's must faster (often close to linear). +bool MatchRegexAnywhere(const char* regex, const char* str) { + if (regex == NULL || str == NULL) + return false; + + if (*regex == '^') + return MatchRegexAtHead(regex + 1, str); + + // A successful match can be anywhere in str. + do { + if (MatchRegexAtHead(regex, str)) + return true; + } while (*str++ != '\0'); + return false; +} + +// Implements the RE class. + +RE::~RE() { + free(const_cast(pattern_)); + free(const_cast(full_pattern_)); +} + +// Returns true iff regular expression re matches the entire str. +bool RE::FullMatch(const char* str, const RE& re) { + return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str); +} + +// Returns true iff regular expression re matches a substring of str +// (including str itself). +bool RE::PartialMatch(const char* str, const RE& re) { + return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str); +} + +// Initializes an RE from its string representation. +void RE::Init(const char* regex) { + pattern_ = full_pattern_ = NULL; + if (regex != NULL) { + pattern_ = posix::StrDup(regex); + } + + is_valid_ = ValidateRegex(regex); + if (!is_valid_) { + // No need to calculate the full pattern when the regex is invalid. + return; + } + + const size_t len = strlen(regex); + // Reserves enough bytes to hold the regular expression used for a + // full match: we need space to prepend a '^', append a '$', and + // terminate the string with '\0'. + char* buffer = static_cast(malloc(len + 3)); + full_pattern_ = buffer; + + if (*regex != '^') + *buffer++ = '^'; // Makes sure full_pattern_ starts with '^'. + + // We don't use snprintf or strncpy, as they trigger a warning when + // compiled with VC++ 8.0. + memcpy(buffer, regex, len); + buffer += len; + + if (len == 0 || regex[len - 1] != '$') + *buffer++ = '$'; // Makes sure full_pattern_ ends with '$'. + + *buffer = '\0'; +} + +#endif // GTEST_USES_POSIX_RE + +const char kUnknownFile[] = "unknown file"; + +// Formats a source file path and a line number as they would appear +// in an error message from the compiler used to compile this code. +GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) { + const std::string file_name(file == NULL ? kUnknownFile : file); + + if (line < 0) { + return file_name + ":"; + } +#ifdef _MSC_VER + return file_name + "(" + StreamableToString(line) + "):"; +#else + return file_name + ":" + StreamableToString(line) + ":"; +#endif // _MSC_VER +} + +// Formats a file location for compiler-independent XML output. +// Although this function is not platform dependent, we put it next to +// FormatFileLocation in order to contrast the two functions. +// Note that FormatCompilerIndependentFileLocation() does NOT append colon +// to the file location it produces, unlike FormatFileLocation(). +GTEST_API_ ::std::string FormatCompilerIndependentFileLocation( + const char* file, int line) { + const std::string file_name(file == NULL ? kUnknownFile : file); + + if (line < 0) + return file_name; + else + return file_name + ":" + StreamableToString(line); +} + + +GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line) + : severity_(severity) { + const char* const marker = + severity == GTEST_INFO ? "[ INFO ]" : + severity == GTEST_WARNING ? "[WARNING]" : + severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]"; + GetStream() << ::std::endl << marker << " " + << FormatFileLocation(file, line).c_str() << ": "; +} + +// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. +GTestLog::~GTestLog() { + GetStream() << ::std::endl; + if (severity_ == GTEST_FATAL) { + fflush(stderr); + posix::Abort(); + } +} +// Disable Microsoft deprecation warnings for POSIX functions called from +// this class (creat, dup, dup2, and close) +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4996) +#endif // _MSC_VER + +#if GTEST_HAS_STREAM_REDIRECTION + +// Object that captures an output stream (stdout/stderr). +class CapturedStream { + public: + // The ctor redirects the stream to a temporary file. + explicit CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) { +# if GTEST_OS_WINDOWS + char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT + char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT + + ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path); + const UINT success = ::GetTempFileNameA(temp_dir_path, + "gtest_redir", + 0, // Generate unique file name. + temp_file_path); + GTEST_CHECK_(success != 0) + << "Unable to create a temporary file in " << temp_dir_path; + const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE); + GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file " + << temp_file_path; + filename_ = temp_file_path; +# else + // There's no guarantee that a test has write access to the current + // directory, so we create the temporary file in the /tmp directory + // instead. We use /tmp on most systems, and /sdcard on Android. + // That's because Android doesn't have /tmp. +# if GTEST_OS_LINUX_ANDROID + // Note: Android applications are expected to call the framework's + // Context.getExternalStorageDirectory() method through JNI to get + // the location of the world-writable SD Card directory. However, + // this requires a Context handle, which cannot be retrieved + // globally from native code. Doing so also precludes running the + // code as part of a regular standalone executable, which doesn't + // run in a Dalvik process (e.g. when running it through 'adb shell'). + // + // The location /sdcard is directly accessible from native code + // and is the only location (unofficially) supported by the Android + // team. It's generally a symlink to the real SD Card mount point + // which can be /mnt/sdcard, /mnt/sdcard0, /system/media/sdcard, or + // other OEM-customized locations. Never rely on these, and always + // use /sdcard. + char name_template[] = "/sdcard/gtest_captured_stream.XXXXXX"; +# else + char name_template[] = "/tmp/captured_stream.XXXXXX"; +# endif // GTEST_OS_LINUX_ANDROID + const int captured_fd = mkstemp(name_template); + filename_ = name_template; +# endif // GTEST_OS_WINDOWS + fflush(NULL); + dup2(captured_fd, fd_); + close(captured_fd); + } + + ~CapturedStream() { + remove(filename_.c_str()); + } + + std::string GetCapturedString() { + if (uncaptured_fd_ != -1) { + // Restores the original stream. + fflush(NULL); + dup2(uncaptured_fd_, fd_); + close(uncaptured_fd_); + uncaptured_fd_ = -1; + } + + FILE* const file = posix::FOpen(filename_.c_str(), "r"); + const std::string content = ReadEntireFile(file); + posix::FClose(file); + return content; + } + + private: + // Reads the entire content of a file as an std::string. + static std::string ReadEntireFile(FILE* file); + + // Returns the size (in bytes) of a file. + static size_t GetFileSize(FILE* file); + + const int fd_; // A stream to capture. + int uncaptured_fd_; + // Name of the temporary file holding the stderr output. + ::std::string filename_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream); +}; + +// Returns the size (in bytes) of a file. +size_t CapturedStream::GetFileSize(FILE* file) { + fseek(file, 0, SEEK_END); + return static_cast(ftell(file)); +} + +// Reads the entire content of a file as a string. +std::string CapturedStream::ReadEntireFile(FILE* file) { + const size_t file_size = GetFileSize(file); + char* const buffer = new char[file_size]; + + size_t bytes_last_read = 0; // # of bytes read in the last fread() + size_t bytes_read = 0; // # of bytes read so far + + fseek(file, 0, SEEK_SET); + + // Keeps reading the file until we cannot read further or the + // pre-determined file size is reached. + do { + bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file); + bytes_read += bytes_last_read; + } while (bytes_last_read > 0 && bytes_read < file_size); + + const std::string content(buffer, bytes_read); + delete[] buffer; + + return content; +} + +# ifdef _MSC_VER +# pragma warning(pop) +# endif // _MSC_VER + +static CapturedStream* g_captured_stderr = NULL; +static CapturedStream* g_captured_stdout = NULL; + +// Starts capturing an output stream (stdout/stderr). +void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) { + if (*stream != NULL) { + GTEST_LOG_(FATAL) << "Only one " << stream_name + << " capturer can exist at a time."; + } + *stream = new CapturedStream(fd); +} + +// Stops capturing the output stream and returns the captured string. +std::string GetCapturedStream(CapturedStream** captured_stream) { + const std::string content = (*captured_stream)->GetCapturedString(); + + delete *captured_stream; + *captured_stream = NULL; + + return content; +} + +// Starts capturing stdout. +void CaptureStdout() { + CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout); +} + +// Starts capturing stderr. +void CaptureStderr() { + CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr); +} + +// Stops capturing stdout and returns the captured string. +std::string GetCapturedStdout() { + return GetCapturedStream(&g_captured_stdout); +} + +// Stops capturing stderr and returns the captured string. +std::string GetCapturedStderr() { + return GetCapturedStream(&g_captured_stderr); +} + +#endif // GTEST_HAS_STREAM_REDIRECTION + +#if GTEST_HAS_DEATH_TEST + +// A copy of all command line arguments. Set by InitGoogleTest(). +::std::vector g_argvs; + +static const ::std::vector* g_injected_test_argvs = + NULL; // Owned. + +void SetInjectableArgvs(const ::std::vector* argvs) { + if (g_injected_test_argvs != argvs) + delete g_injected_test_argvs; + g_injected_test_argvs = argvs; +} + +const ::std::vector& GetInjectableArgvs() { + if (g_injected_test_argvs != NULL) { + return *g_injected_test_argvs; + } + return g_argvs; +} +#endif // GTEST_HAS_DEATH_TEST + +#if GTEST_OS_WINDOWS_MOBILE +namespace posix { +void Abort() { + DebugBreak(); + TerminateProcess(GetCurrentProcess(), 1); +} +} // namespace posix +#endif // GTEST_OS_WINDOWS_MOBILE + +// Returns the name of the environment variable corresponding to the +// given flag. For example, FlagToEnvVar("foo") will return +// "GTEST_FOO" in the open-source version. +static std::string FlagToEnvVar(const char* flag) { + const std::string full_flag = + (Message() << GTEST_FLAG_PREFIX_ << flag).GetString(); + + Message env_var; + for (size_t i = 0; i != full_flag.length(); i++) { + env_var << ToUpper(full_flag.c_str()[i]); + } + + return env_var.GetString(); +} + +// Parses 'str' for a 32-bit signed integer. If successful, writes +// the result to *value and returns true; otherwise leaves *value +// unchanged and returns false. +bool ParseInt32(const Message& src_text, const char* str, Int32* value) { + // Parses the environment variable as a decimal integer. + char* end = NULL; + const long long_value = strtol(str, &end, 10); // NOLINT + + // Has strtol() consumed all characters in the string? + if (*end != '\0') { + // No - an invalid character was encountered. + Message msg; + msg << "WARNING: " << src_text + << " is expected to be a 32-bit integer, but actually" + << " has value \"" << str << "\".\n"; + printf("%s", msg.GetString().c_str()); + fflush(stdout); + return false; + } + + // Is the parsed value in the range of an Int32? + const Int32 result = static_cast(long_value); + if (long_value == LONG_MAX || long_value == LONG_MIN || + // The parsed value overflows as a long. (strtol() returns + // LONG_MAX or LONG_MIN when the input overflows.) + result != long_value + // The parsed value overflows as an Int32. + ) { + Message msg; + msg << "WARNING: " << src_text + << " is expected to be a 32-bit integer, but actually" + << " has value " << str << ", which overflows.\n"; + printf("%s", msg.GetString().c_str()); + fflush(stdout); + return false; + } + + *value = result; + return true; +} + +// Reads and returns the Boolean environment variable corresponding to +// the given flag; if it's not set, returns default_value. +// +// The value is considered true iff it's not "0". +bool BoolFromGTestEnv(const char* flag, bool default_value) { + const std::string env_var = FlagToEnvVar(flag); + const char* const string_value = posix::GetEnv(env_var.c_str()); + return string_value == NULL ? + default_value : strcmp(string_value, "0") != 0; +} + +// Reads and returns a 32-bit integer stored in the environment +// variable corresponding to the given flag; if it isn't set or +// doesn't represent a valid 32-bit integer, returns default_value. +Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) { + const std::string env_var = FlagToEnvVar(flag); + const char* const string_value = posix::GetEnv(env_var.c_str()); + if (string_value == NULL) { + // The environment variable is not set. + return default_value; + } + + Int32 result = default_value; + if (!ParseInt32(Message() << "Environment variable " << env_var, + string_value, &result)) { + printf("The default value %s is used.\n", + (Message() << default_value).GetString().c_str()); + fflush(stdout); + return default_value; + } + + return result; +} + +// Reads and returns the string environment variable corresponding to +// the given flag; if it's not set, returns default_value. +const char* StringFromGTestEnv(const char* flag, const char* default_value) { + const std::string env_var = FlagToEnvVar(flag); + const char* const value = posix::GetEnv(env_var.c_str()); + return value == NULL ? default_value : value; +} + +} // namespace internal +} // namespace testing +// 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) + +// Google Test - The Google C++ Testing Framework +// +// This file implements a universal value printer that can print a +// value of any type T: +// +// void ::testing::internal::UniversalPrinter::Print(value, ostream_ptr); +// +// It uses the << operator when possible, and prints the bytes in the +// object otherwise. A user can override its behavior for a class +// type Foo by defining either operator<<(::std::ostream&, const Foo&) +// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that +// defines Foo. + +#include +#include +#include // NOLINT +#include + +namespace testing { + +namespace { + +using ::std::ostream; + +// Prints a segment of bytes in the given object. +void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start, + size_t count, ostream* os) { + char text[5] = ""; + for (size_t i = 0; i != count; i++) { + const size_t j = start + i; + if (i != 0) { + // Organizes the bytes into groups of 2 for easy parsing by + // human. + if ((j % 2) == 0) + *os << ' '; + else + *os << '-'; + } + GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]); + *os << text; + } +} + +// Prints the bytes in the given value to the given ostream. +void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count, + ostream* os) { + // Tells the user how big the object is. + *os << count << "-byte object <"; + + const size_t kThreshold = 132; + const size_t kChunkSize = 64; + // If the object size is bigger than kThreshold, we'll have to omit + // some details by printing only the first and the last kChunkSize + // bytes. + // TODO(wan): let the user control the threshold using a flag. + if (count < kThreshold) { + PrintByteSegmentInObjectTo(obj_bytes, 0, count, os); + } else { + PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os); + *os << " ... "; + // Rounds up to 2-byte boundary. + const size_t resume_pos = (count - kChunkSize + 1)/2*2; + PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os); + } + *os << ">"; +} + +} // namespace + +namespace internal2 { + +// Delegates to PrintBytesInObjectToImpl() to print the bytes in the +// given object. The delegation simplifies the implementation, which +// uses the << operator and thus is easier done outside of the +// ::testing::internal namespace, which contains a << operator that +// sometimes conflicts with the one in STL. +void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count, + ostream* os) { + PrintBytesInObjectToImpl(obj_bytes, count, os); +} + +} // namespace internal2 + +namespace internal { + +// Depending on the value of a char (or wchar_t), we print it in one +// of three formats: +// - as is if it's a printable ASCII (e.g. 'a', '2', ' '), +// - as a hexidecimal escape sequence (e.g. '\x7F'), or +// - as a special escape sequence (e.g. '\r', '\n'). +enum CharFormat { + kAsIs, + kHexEscape, + kSpecialEscape +}; + +// Returns true if c is a printable ASCII character. We test the +// value of c directly instead of calling isprint(), which is buggy on +// Windows Mobile. +inline bool IsPrintableAscii(wchar_t c) { + return 0x20 <= c && c <= 0x7E; +} + +// Prints a wide or narrow char c as a character literal without the +// quotes, escaping it when necessary; returns how c was formatted. +// The template argument UnsignedChar is the unsigned version of Char, +// which is the type of c. +template +static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) { + switch (static_cast(c)) { + case L'\0': + *os << "\\0"; + break; + case L'\'': + *os << "\\'"; + break; + case L'\\': + *os << "\\\\"; + break; + case L'\a': + *os << "\\a"; + break; + case L'\b': + *os << "\\b"; + break; + case L'\f': + *os << "\\f"; + break; + case L'\n': + *os << "\\n"; + break; + case L'\r': + *os << "\\r"; + break; + case L'\t': + *os << "\\t"; + break; + case L'\v': + *os << "\\v"; + break; + default: + if (IsPrintableAscii(c)) { + *os << static_cast(c); + return kAsIs; + } else { + *os << "\\x" + String::FormatHexInt(static_cast(c)); + return kHexEscape; + } + } + return kSpecialEscape; +} + +// Prints a wchar_t c as if it's part of a string literal, escaping it when +// necessary; returns how c was formatted. +static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) { + switch (c) { + case L'\'': + *os << "'"; + return kAsIs; + case L'"': + *os << "\\\""; + return kSpecialEscape; + default: + return PrintAsCharLiteralTo(c, os); + } +} + +// Prints a char c as if it's part of a string literal, escaping it when +// necessary; returns how c was formatted. +static CharFormat PrintAsStringLiteralTo(char c, ostream* os) { + return PrintAsStringLiteralTo( + static_cast(static_cast(c)), os); +} + +// Prints a wide or narrow character c and its code. '\0' is printed +// as "'\\0'", other unprintable characters are also properly escaped +// using the standard C++ escape sequence. The template argument +// UnsignedChar is the unsigned version of Char, which is the type of c. +template +void PrintCharAndCodeTo(Char c, ostream* os) { + // First, print c as a literal in the most readable form we can find. + *os << ((sizeof(c) > 1) ? "L'" : "'"); + const CharFormat format = PrintAsCharLiteralTo(c, os); + *os << "'"; + + // To aid user debugging, we also print c's code in decimal, unless + // it's 0 (in which case c was printed as '\\0', making the code + // obvious). + if (c == 0) + return; + *os << " (" << static_cast(c); + + // For more convenience, we print c's code again in hexidecimal, + // unless c was already printed in the form '\x##' or the code is in + // [1, 9]. + if (format == kHexEscape || (1 <= c && c <= 9)) { + // Do nothing. + } else { + *os << ", 0x" << String::FormatHexInt(static_cast(c)); + } + *os << ")"; +} + +void PrintTo(unsigned char c, ::std::ostream* os) { + PrintCharAndCodeTo(c, os); +} +void PrintTo(signed char c, ::std::ostream* os) { + PrintCharAndCodeTo(c, os); +} + +// Prints a wchar_t as a symbol if it is printable or as its internal +// code otherwise and also as its code. L'\0' is printed as "L'\\0'". +void PrintTo(wchar_t wc, ostream* os) { + PrintCharAndCodeTo(wc, os); +} + +// Prints the given array of characters to the ostream. CharType must be either +// char or wchar_t. +// The array starts at begin, the length is len, it may include '\0' characters +// and may not be NUL-terminated. +template +static void PrintCharsAsStringTo( + const CharType* begin, size_t len, ostream* os) { + const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\""; + *os << kQuoteBegin; + bool is_previous_hex = false; + for (size_t index = 0; index < len; ++index) { + const CharType cur = begin[index]; + if (is_previous_hex && IsXDigit(cur)) { + // Previous character is of '\x..' form and this character can be + // interpreted as another hexadecimal digit in its number. Break string to + // disambiguate. + *os << "\" " << kQuoteBegin; + } + is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape; + } + *os << "\""; +} + +// Prints a (const) char/wchar_t array of 'len' elements, starting at address +// 'begin'. CharType must be either char or wchar_t. +template +static void UniversalPrintCharArray( + const CharType* begin, size_t len, ostream* os) { + // The code + // const char kFoo[] = "foo"; + // generates an array of 4, not 3, elements, with the last one being '\0'. + // + // Therefore when printing a char array, we don't print the last element if + // it's '\0', such that the output matches the string literal as it's + // written in the source code. + if (len > 0 && begin[len - 1] == '\0') { + PrintCharsAsStringTo(begin, len - 1, os); + return; + } + + // If, however, the last element in the array is not '\0', e.g. + // const char kFoo[] = { 'f', 'o', 'o' }; + // we must print the entire array. We also print a message to indicate + // that the array is not NUL-terminated. + PrintCharsAsStringTo(begin, len, os); + *os << " (no terminating NUL)"; +} + +// Prints a (const) char array of 'len' elements, starting at address 'begin'. +void UniversalPrintArray(const char* begin, size_t len, ostream* os) { + UniversalPrintCharArray(begin, len, os); +} + +// Prints a (const) wchar_t array of 'len' elements, starting at address +// 'begin'. +void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) { + UniversalPrintCharArray(begin, len, os); +} + +// Prints the given C string to the ostream. +void PrintTo(const char* s, ostream* os) { + if (s == NULL) { + *os << "NULL"; + } else { + *os << ImplicitCast_(s) << " pointing to "; + PrintCharsAsStringTo(s, strlen(s), os); + } +} + +// MSVC compiler can be configured to define whar_t as a typedef +// of unsigned short. Defining an overload for const wchar_t* in that case +// would cause pointers to unsigned shorts be printed as wide strings, +// possibly accessing more memory than intended and causing invalid +// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when +// wchar_t is implemented as a native type. +#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) +// Prints the given wide C string to the ostream. +void PrintTo(const wchar_t* s, ostream* os) { + if (s == NULL) { + *os << "NULL"; + } else { + *os << ImplicitCast_(s) << " pointing to "; + PrintCharsAsStringTo(s, wcslen(s), os); + } +} +#endif // wchar_t is native + +// Prints a ::string object. +#if GTEST_HAS_GLOBAL_STRING +void PrintStringTo(const ::string& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_GLOBAL_STRING + +void PrintStringTo(const ::std::string& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} + +// Prints a ::wstring object. +#if GTEST_HAS_GLOBAL_WSTRING +void PrintWideStringTo(const ::wstring& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_GLOBAL_WSTRING + +#if GTEST_HAS_STD_WSTRING +void PrintWideStringTo(const ::std::wstring& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_STD_WSTRING + +} // namespace internal + +} // namespace testing +// Copyright 2008, 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: mheule@google.com (Markus Heule) +// +// The Google C++ Testing Framework (Google Test) + + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +#undef GTEST_IMPLEMENTATION_ + +namespace testing { + +using internal::GetUnitTestImpl; + +// Gets the summary of the failure message by omitting the stack trace +// in it. +std::string TestPartResult::ExtractSummary(const char* message) { + const char* const stack_trace = strstr(message, internal::kStackTraceMarker); + return stack_trace == NULL ? message : + std::string(message, stack_trace); +} + +// Prints a TestPartResult object. +std::ostream& operator<<(std::ostream& os, const TestPartResult& result) { + return os + << result.file_name() << ":" << result.line_number() << ": " + << (result.type() == TestPartResult::kSuccess ? "Success" : + result.type() == TestPartResult::kFatalFailure ? "Fatal failure" : + "Non-fatal failure") << ":\n" + << result.message() << std::endl; +} + +// Appends a TestPartResult to the array. +void TestPartResultArray::Append(const TestPartResult& result) { + array_.push_back(result); +} + +// Returns the TestPartResult at the given index (0-based). +const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const { + if (index < 0 || index >= size()) { + printf("\nInvalid index (%d) into TestPartResultArray.\n", index); + internal::posix::Abort(); + } + + return array_[index]; +} + +// Returns the number of TestPartResult objects in the array. +int TestPartResultArray::size() const { + return static_cast(array_.size()); +} + +namespace internal { + +HasNewFatalFailureHelper::HasNewFatalFailureHelper() + : has_new_fatal_failure_(false), + original_reporter_(GetUnitTestImpl()-> + GetTestPartResultReporterForCurrentThread()) { + GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this); +} + +HasNewFatalFailureHelper::~HasNewFatalFailureHelper() { + GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread( + original_reporter_); +} + +void HasNewFatalFailureHelper::ReportTestPartResult( + const TestPartResult& result) { + if (result.fatally_failed()) + has_new_fatal_failure_ = true; + original_reporter_->ReportTestPartResult(result); +} + +} // namespace internal + +} // namespace testing +// Copyright 2008 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) + + +namespace testing { +namespace internal { + +#if GTEST_HAS_TYPED_TEST_P + +// Skips to the first non-space char in str. Returns an empty string if str +// contains only whitespace characters. +static const char* SkipSpaces(const char* str) { + while (IsSpace(*str)) + str++; + return str; +} + +// Verifies that registered_tests match the test names in +// defined_test_names_; returns registered_tests if successful, or +// aborts the program otherwise. +const char* TypedTestCasePState::VerifyRegisteredTestNames( + const char* file, int line, const char* registered_tests) { + typedef ::std::set::const_iterator DefinedTestIter; + registered_ = true; + + // Skip initial whitespace in registered_tests since some + // preprocessors prefix stringizied literals with whitespace. + registered_tests = SkipSpaces(registered_tests); + + Message errors; + ::std::set tests; + for (const char* names = registered_tests; names != NULL; + names = SkipComma(names)) { + const std::string name = GetPrefixUntilComma(names); + if (tests.count(name) != 0) { + errors << "Test " << name << " is listed more than once.\n"; + continue; + } + + bool found = false; + for (DefinedTestIter it = defined_test_names_.begin(); + it != defined_test_names_.end(); + ++it) { + if (name == *it) { + found = true; + break; + } + } + + if (found) { + tests.insert(name); + } else { + errors << "No test named " << name + << " can be found in this test case.\n"; + } + } + + for (DefinedTestIter it = defined_test_names_.begin(); + it != defined_test_names_.end(); + ++it) { + if (tests.count(*it) == 0) { + errors << "You forgot to list test " << *it << ".\n"; + } + } + + const std::string& errors_str = errors.GetString(); + if (errors_str != "") { + fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), + errors_str.c_str()); + fflush(stderr); + posix::Abort(); + } + + return registered_tests; +} + +#endif // GTEST_HAS_TYPED_TEST_P + +} // namespace internal +} // namespace testing diff --git a/gtest/gtest.h b/gtest/gtest.h new file mode 100644 index 000000000..6e7cfc2be --- /dev/null +++ b/gtest/gtest.h @@ -0,0 +1,20063 @@ +// 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 +// 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) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines the public API for Google Test. It should be +// included by any test program that uses Google Test. +// +// IMPORTANT NOTE: Due to limitation of the C++ language, we have to +// leave some internal implementation details in this header file. +// They are clearly marked by comments like this: +// +// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +// +// Such code is NOT meant to be used by a user directly, and is subject +// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user +// program! +// +// Acknowledgment: Google Test borrowed the idea of automatic test +// registration from Barthelemy Dagenais' (barthelemy@prologique.com) +// easyUnit framework. + +#define _VARIADIC_MAX 10 + +#ifndef GTEST_INCLUDE_GTEST_GTEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_H_ + +#include +#include +#include + +// 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 +// 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. +// +// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file declares functions and macros used internally by +// Google Test. They are subject to change without notice. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ + +// 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 +// 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. +// +// Authors: wan@google.com (Zhanyong Wan) +// +// Low-level types and utilities for porting Google Test to various +// platforms. They are subject to change without notice. DO NOT USE +// THEM IN USER CODE. +// +// This file is fundamental to Google Test. All other Google Test source +// files are expected to #include this. Therefore, it cannot #include +// any other Google Test header. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ + +// The user can define the following macros in the build script to +// control Google Test's behavior. If the user doesn't define a macro +// in this list, Google Test will define it. +// +// GTEST_HAS_CLONE - Define it to 1/0 to indicate that clone(2) +// is/isn't available. +// GTEST_HAS_EXCEPTIONS - Define it to 1/0 to indicate that exceptions +// are enabled. +// GTEST_HAS_GLOBAL_STRING - Define it to 1/0 to indicate that ::string +// is/isn't available (some systems define +// ::string, which is different to std::string). +// GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::string +// is/isn't available (some systems define +// ::wstring, which is different to std::wstring). +// GTEST_HAS_POSIX_RE - Define it to 1/0 to indicate that POSIX regular +// expressions are/aren't available. +// GTEST_HAS_PTHREAD - Define it to 1/0 to indicate that +// is/isn't available. +// GTEST_HAS_RTTI - Define it to 1/0 to indicate that RTTI is/isn't +// enabled. +// 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 - 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_HAS_STREAM_REDIRECTION +// - Define it to 1/0 to indicate whether the +// platform supports I/O stream redirection using +// dup() and dup2(). +// 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. +// GTEST_LANG_CXX11 - Define it to 1/0 to indicate that Google Test +// is building in C++11/C++98 mode. +// GTEST_LINKED_AS_SHARED_LIBRARY +// - Define to 1 when compiling tests that use +// Google Test as a shared library (known as +// DLL on Windows). +// GTEST_CREATE_SHARED_LIBRARY +// - Define to 1 when compiling Google Test itself +// as a shared library. + +// This header defines the following utilities: +// +// Macros indicating the current platform (defined to 1 if compiled on +// the given platform; otherwise undefined): +// GTEST_OS_AIX - IBM AIX +// GTEST_OS_CYGWIN - Cygwin +// GTEST_OS_HPUX - HP-UX +// GTEST_OS_LINUX - Linux +// GTEST_OS_LINUX_ANDROID - Google Android +// GTEST_OS_MAC - Mac OS X +// GTEST_OS_IOS - iOS +// GTEST_OS_IOS_SIMULATOR - iOS simulator +// GTEST_OS_NACL - Google Native Client (NaCl) +// GTEST_OS_OPENBSD - OpenBSD +// GTEST_OS_QNX - QNX +// GTEST_OS_SOLARIS - Sun Solaris +// GTEST_OS_SYMBIAN - Symbian +// GTEST_OS_WINDOWS - Windows (Desktop, MinGW, or Mobile) +// GTEST_OS_WINDOWS_DESKTOP - Windows Desktop +// GTEST_OS_WINDOWS_MINGW - MinGW +// GTEST_OS_WINDOWS_MOBILE - Windows Mobile +// GTEST_OS_ZOS - z/OS +// +// Among the platforms, Cygwin, Linux, Max OS X, and Windows have the +// most stable support. Since core members of the Google Test project +// don't have access to other platforms, support for them may be less +// stable. If you notice any problems on your platform, please notify +// googletestframework@googlegroups.com (patches for fixing them are +// even more welcome!). +// +// Note that it is possible that none of the GTEST_OS_* macros are defined. +// +// Macros indicating available Google Test features (defined to 1 if +// the corresponding feature is supported; otherwise undefined): +// GTEST_HAS_COMBINE - the Combine() function (for value-parameterized +// tests) +// GTEST_HAS_DEATH_TEST - death tests +// GTEST_HAS_PARAM_TEST - value-parameterized tests +// GTEST_HAS_TYPED_TEST - typed tests +// GTEST_HAS_TYPED_TEST_P - type-parameterized tests +// GTEST_USES_POSIX_RE - enhanced POSIX regex is used. Do not confuse with +// GTEST_HAS_POSIX_RE (see above) which users can +// define themselves. +// GTEST_USES_SIMPLE_RE - our own simple regex is used; +// the above two are mutually exclusive. +// GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ(). +// +// Macros for basic C++ coding: +// GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning. +// GTEST_ATTRIBUTE_UNUSED_ - declares that a class' instances or a +// variable don't have to be used. +// GTEST_DISALLOW_ASSIGN_ - disables operator=. +// GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=. +// GTEST_MUST_USE_RESULT_ - declares that a function's result must be used. +// +// Synchronization: +// Mutex, MutexLock, ThreadLocal, GetThreadCount() +// - synchronization primitives. +// GTEST_IS_THREADSAFE - defined to 1 to indicate that the above +// synchronization primitives have real implementations +// and Google Test is thread-safe; or 0 otherwise. +// +// Template meta programming: +// is_pointer - as in TR1; needed on Symbian and IBM XL C/C++ only. +// IteratorTraits - partial implementation of std::iterator_traits, which +// is not available in libCstd when compiled with Sun C++. +// +// Smart pointers: +// scoped_ptr - as in TR2. +// +// Regular expressions: +// RE - a simple regular expression class using the POSIX +// Extended Regular Expression syntax on UNIX-like +// platforms, or a reduced regular exception syntax on +// other platforms, including Windows. +// +// Logging: +// GTEST_LOG_() - logs messages at the specified severity level. +// LogToStderr() - directs all log messages to stderr. +// FlushInfoLog() - flushes informational log messages. +// +// Stdout and stderr capturing: +// CaptureStdout() - starts capturing stdout. +// GetCapturedStdout() - stops capturing stdout and returns the captured +// string. +// CaptureStderr() - starts capturing stderr. +// GetCapturedStderr() - stops capturing stderr and returns the captured +// string. +// +// Integer types: +// TypeWithSize - maps an integer to a int type. +// Int32, UInt32, Int64, UInt64, TimeInMillis +// - integers of known sizes. +// BiggestInt - the biggest signed integer type. +// +// Command-line utilities: +// GTEST_FLAG() - references a flag. +// GTEST_DECLARE_*() - declares a flag. +// GTEST_DEFINE_*() - defines a flag. +// GetInjectableArgvs() - returns the command line as a vector of strings. +// +// Environment variable utilities: +// GetEnv() - gets the value of an environment variable. +// BoolFromGTestEnv() - parses a bool environment variable. +// Int32FromGTestEnv() - parses an Int32 environment variable. +// StringFromGTestEnv() - parses a string environment variable. + +#include // for isspace, etc +#include // for ptrdiff_t +#include +#include +#include +#ifndef _WIN32_WCE +# include +# include +#endif // !_WIN32_WCE + +#if defined __APPLE__ +# include +# include +#endif + +#include // NOLINT +#include // NOLINT +#include // NOLINT + +#define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com" +#define GTEST_FLAG_PREFIX_ "gtest_" +#define GTEST_FLAG_PREFIX_DASH_ "gtest-" +#define GTEST_FLAG_PREFIX_UPPER_ "GTEST_" +#define GTEST_NAME_ "Google Test" +#define GTEST_PROJECT_URL_ "http://code.google.com/p/googletest/" + +// Determines the version of gcc that is used to compile this. +#ifdef __GNUC__ +// 40302 means version 4.3.2. +# define GTEST_GCC_VER_ \ + (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__) +#endif // __GNUC__ + +// Determines the platform on which Google Test is compiled. +#ifdef __CYGWIN__ +# define GTEST_OS_CYGWIN 1 +#elif defined __SYMBIAN32__ +# define GTEST_OS_SYMBIAN 1 +#elif defined _WIN32 +# define GTEST_OS_WINDOWS 1 +# ifdef _WIN32_WCE +# define GTEST_OS_WINDOWS_MOBILE 1 +# elif defined(__MINGW__) || defined(__MINGW32__) +# define GTEST_OS_WINDOWS_MINGW 1 +# else +# define GTEST_OS_WINDOWS_DESKTOP 1 +# endif // _WIN32_WCE +#elif defined __APPLE__ +# define GTEST_OS_MAC 1 +# if TARGET_OS_IPHONE +# define GTEST_OS_IOS 1 +# if TARGET_IPHONE_SIMULATOR +# define GTEST_OS_IOS_SIMULATOR 1 +# endif +# endif +#elif defined __linux__ +# define GTEST_OS_LINUX 1 +# if defined __ANDROID__ +# define GTEST_OS_LINUX_ANDROID 1 +# endif +#elif defined __MVS__ +# define GTEST_OS_ZOS 1 +#elif defined(__sun) && defined(__SVR4) +# define GTEST_OS_SOLARIS 1 +#elif defined(_AIX) +# define GTEST_OS_AIX 1 +#elif defined(__hpux) +# define GTEST_OS_HPUX 1 +#elif defined __native_client__ +# define GTEST_OS_NACL 1 +#elif defined __OpenBSD__ +# define GTEST_OS_OPENBSD 1 +#elif defined __QNX__ +# define GTEST_OS_QNX 1 +#endif // __CYGWIN__ + +#ifndef GTEST_LANG_CXX11 +// gcc and clang define __GXX_EXPERIMENTAL_CXX0X__ when +// -std={c,gnu}++{0x,11} is passed. The C++11 standard specifies a +// value for __cplusplus, and recent versions of clang, gcc, and +// probably other compilers set that too in C++11 mode. +# if __GXX_EXPERIMENTAL_CXX0X__ || __cplusplus >= 201103L +// Compiling in at least C++11 mode. +# define GTEST_LANG_CXX11 1 +# else +# define GTEST_LANG_CXX11 0 +# endif +#endif + +// Brings in definitions for functions used in the testing::internal::posix +// namespace (read, write, close, chdir, isatty, stat). We do not currently +// use them on Windows Mobile. +#if !GTEST_OS_WINDOWS +// This assumes that non-Windows OSes provide unistd.h. For OSes where this +// is not the case, we need to include headers that provide the functions +// mentioned above. +# include +# include +#elif !GTEST_OS_WINDOWS_MOBILE +# include +# include +#endif + +#if GTEST_OS_LINUX_ANDROID +// Used to define __ANDROID_API__ matching the target NDK API level. +# include // NOLINT +#endif + +// Defines this to true iff Google Test can use POSIX regular expressions. +#ifndef GTEST_HAS_POSIX_RE +# if GTEST_OS_LINUX_ANDROID +// On Android, is only available starting with Gingerbread. +# define GTEST_HAS_POSIX_RE (__ANDROID_API__ >= 9) +# else +# define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS) +# endif +#endif + +#if GTEST_HAS_POSIX_RE + +// On some platforms, needs someone to define size_t, and +// won't compile otherwise. We can #include it here as we already +// included , which is guaranteed to define size_t through +// . +# include // NOLINT + +# define GTEST_USES_POSIX_RE 1 + +#elif GTEST_OS_WINDOWS + +// is not available on Windows. Use our own simple regex +// implementation instead. +# define GTEST_USES_SIMPLE_RE 1 + +#else + +// may not be available on this platform. Use our own +// simple regex implementation instead. +# define GTEST_USES_SIMPLE_RE 1 + +#endif // GTEST_HAS_POSIX_RE + +#ifndef GTEST_HAS_EXCEPTIONS +// The user didn't tell us whether exceptions are enabled, so we need +// to figure it out. +# if defined(_MSC_VER) || defined(__BORLANDC__) +// MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS +// macro to enable exceptions, so we'll do the same. +// Assumes that exceptions are enabled by default. +# ifndef _HAS_EXCEPTIONS +# define _HAS_EXCEPTIONS 1 +# endif // _HAS_EXCEPTIONS +# define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS +# elif defined(__GNUC__) && __EXCEPTIONS +// gcc defines __EXCEPTIONS to 1 iff exceptions are enabled. +# define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__SUNPRO_CC) +// Sun Pro CC supports exceptions. However, there is no compile-time way of +// detecting whether they are enabled or not. Therefore, we assume that +// they are enabled unless the user tells us otherwise. +# define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__IBMCPP__) && __EXCEPTIONS +// xlC defines __EXCEPTIONS to 1 iff exceptions are enabled. +# define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__HP_aCC) +// Exception handling is in effect by default in HP aCC compiler. It has to +// be turned of by +noeh compiler option if desired. +# define GTEST_HAS_EXCEPTIONS 1 +# else +// For other compilers, we assume exceptions are disabled to be +// conservative. +# define GTEST_HAS_EXCEPTIONS 0 +# endif // defined(_MSC_VER) || defined(__BORLANDC__) +#endif // GTEST_HAS_EXCEPTIONS + +#if !defined(GTEST_HAS_STD_STRING) +// Even though we don't use this macro any longer, we keep it in case +// some clients still depend on it. +# define GTEST_HAS_STD_STRING 1 +#elif !GTEST_HAS_STD_STRING +// The user told us that ::std::string isn't available. +# error "Google Test cannot be used where ::std::string isn't available." +#endif // !defined(GTEST_HAS_STD_STRING) + +#ifndef GTEST_HAS_GLOBAL_STRING +// The user didn't tell us whether ::string is available, so we need +// to figure it out. + +# define GTEST_HAS_GLOBAL_STRING 0 + +#endif // GTEST_HAS_GLOBAL_STRING + +#ifndef GTEST_HAS_STD_WSTRING +// The user didn't tell us whether ::std::wstring is available, so we need +// to figure it out. +// TODO(wan@google.com): uses autoconf to detect whether ::std::wstring +// is available. + +// Cygwin 1.7 and below doesn't support ::std::wstring. +// Solaris' libc++ doesn't support it either. Android has +// no support for it at least as recent as Froyo (2.2). +# define GTEST_HAS_STD_WSTRING \ + (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS)) + +#endif // GTEST_HAS_STD_WSTRING + +#ifndef GTEST_HAS_GLOBAL_WSTRING +// The user didn't tell us whether ::wstring is available, so we need +// to figure it out. +# define GTEST_HAS_GLOBAL_WSTRING \ + (GTEST_HAS_STD_WSTRING && GTEST_HAS_GLOBAL_STRING) +#endif // GTEST_HAS_GLOBAL_WSTRING + +// Determines whether RTTI is available. +#ifndef GTEST_HAS_RTTI +// The user didn't tell us whether RTTI is enabled, so we need to +// figure it out. + +# ifdef _MSC_VER + +# ifdef _CPPRTTI // MSVC defines this macro iff RTTI is enabled. +# define GTEST_HAS_RTTI 1 +# else +# define GTEST_HAS_RTTI 0 +# endif + +// Starting with version 4.3.2, gcc defines __GXX_RTTI iff RTTI is enabled. +# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302) + +# ifdef __GXX_RTTI +// When building against STLport with the Android NDK and with +// -frtti -fno-exceptions, the build fails at link time with undefined +// references to __cxa_bad_typeid. Note sure if STL or toolchain bug, +// so disable RTTI when detected. +# if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR) && \ + !defined(__EXCEPTIONS) +# define GTEST_HAS_RTTI 0 +# else +# define GTEST_HAS_RTTI 1 +# endif // GTEST_OS_LINUX_ANDROID && __STLPORT_MAJOR && !__EXCEPTIONS +# else +# define GTEST_HAS_RTTI 0 +# endif // __GXX_RTTI + +// Clang defines __GXX_RTTI starting with version 3.0, but its manual recommends +// using has_feature instead. has_feature(cxx_rtti) is supported since 2.7, the +// first version with C++ support. +# elif defined(__clang__) + +# define GTEST_HAS_RTTI __has_feature(cxx_rtti) + +// Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if +// both the typeid and dynamic_cast features are present. +# elif defined(__IBMCPP__) && (__IBMCPP__ >= 900) + +# ifdef __RTTI_ALL__ +# define GTEST_HAS_RTTI 1 +# else +# define GTEST_HAS_RTTI 0 +# endif + +# else + +// For all other compilers, we assume RTTI is enabled. +# define GTEST_HAS_RTTI 1 + +# endif // _MSC_VER + +#endif // GTEST_HAS_RTTI + +// It's this header's responsibility to #include when RTTI +// is enabled. +#if GTEST_HAS_RTTI +# include +#endif + +// Determines whether Google Test can use the pthreads library. +#ifndef GTEST_HAS_PTHREAD +// The user didn't tell us explicitly, so we assume pthreads support is +// available on Linux and Mac. +// +// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0 +// to your compiler flags. +# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX \ + || GTEST_OS_QNX) +#endif // GTEST_HAS_PTHREAD + +#if GTEST_HAS_PTHREAD +// gtest-port.h guarantees to #include when GTEST_HAS_PTHREAD is +// true. +# include // NOLINT + +// For timespec and nanosleep, used below. +# include // NOLINT +#endif + +// 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 +# if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR) +// STLport, provided with the Android NDK, has neither or . +# define GTEST_HAS_TR1_TUPLE 0 +# else +// The user didn't tell us not to do it, so we assume it's OK. +# define GTEST_HAS_TR1_TUPLE 1 +# endif +#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. + +// We use our own TR1 tuple if we aren't sure the user has an +// implementation of it already. At this time, libstdc++ 4.0.0+ and +// MSVC 2010 are the only mainstream standard libraries that come +// with a TR1 tuple implementation. NVIDIA's CUDA NVCC compiler +// pretends to be GCC by defining __GNUC__ and friends, but cannot +// compile GCC's tuple implementation. MSVC 2008 (9.0) provides TR1 +// tuple in a 323 MB Feature Pack download, which we cannot assume the +// user has. QNX's QCC compiler is a modified GCC but it doesn't +// support TR1 tuple. libc++ only provides std::tuple, in C++11 mode, +// and it can be used with some compilers that define __GNUC__. +# if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000) \ + && !GTEST_OS_QNX && !defined(_LIBCPP_VERSION)) || _MSC_VER >= 1600 +# define GTEST_ENV_HAS_TR1_TUPLE_ 1 +# endif + +// C++11 specifies that provides std::tuple. Use that if gtest is used +// in C++11 mode and libstdc++ isn't very old (binaries targeting OS X 10.6 +// can build with clang but need to use gcc4.2's libstdc++). +# if GTEST_LANG_CXX11 && (!defined(__GLIBCXX__) || __GLIBCXX__ > 20110325) +# define GTEST_ENV_HAS_STD_TUPLE_ 1 +# endif + +# if GTEST_ENV_HAS_TR1_TUPLE_ || GTEST_ENV_HAS_STD_TUPLE_ +# define GTEST_USE_OWN_TR1_TUPLE 0 +# else +# define GTEST_USE_OWN_TR1_TUPLE 1 +# endif + +#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_USE_OWN_TR1_TUPLE +// This file was GENERATED by command: +// pump.py gtest-tuple.h.pump +// 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_INTERNAL_GTEST_TUPLE_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ + +#include // For ::std::pair. + +// The compiler used in Symbian has a bug that prevents us from declaring the +// tuple template as a friend (it complains that tuple is redefined). This +// hack bypasses the bug by declaring the members that should otherwise be +// private as public. +// Sun Studio versions < 12 also have the above bug. +#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590) +# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public: +#else +# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \ + template friend class tuple; \ + private: +#endif + +// GTEST_n_TUPLE_(T) is the type of an n-tuple. +#define GTEST_0_TUPLE_(T) tuple<> +#define GTEST_1_TUPLE_(T) tuple +#define GTEST_2_TUPLE_(T) tuple +#define GTEST_3_TUPLE_(T) tuple +#define GTEST_4_TUPLE_(T) tuple +#define GTEST_5_TUPLE_(T) tuple +#define GTEST_6_TUPLE_(T) tuple +#define GTEST_7_TUPLE_(T) tuple +#define GTEST_8_TUPLE_(T) tuple +#define GTEST_9_TUPLE_(T) tuple +#define GTEST_10_TUPLE_(T) tuple + +// 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 +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::type is T if T is a reference; otherwise it's const T&. +template +struct ByRef { typedef const T& type; }; // NOLINT +template +struct ByRef { typedef T& type; }; // NOLINT + +// A handy wrapper for ByRef. +#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef::type + +// AddRef::type is T if T is a reference; otherwise it's T&. This +// is the same as tr1::add_reference::type. +template +struct AddRef { typedef T& type; }; // NOLINT +template +struct AddRef { typedef T& type; }; // NOLINT + +// A handy wrapper for AddRef. +#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef::type + +// A helper for implementing get(). +template class Get; + +// A helper for implementing tuple_element. kIndexValid is true +// iff k < the number of fields in tuple type T. +template +struct TupleElement; + +template +struct TupleElement { + typedef T0 type; +}; + +template +struct TupleElement { + typedef T1 type; +}; + +template +struct TupleElement { + typedef T2 type; +}; + +template +struct TupleElement { + typedef T3 type; +}; + +template +struct TupleElement { + typedef T4 type; +}; + +template +struct TupleElement { + typedef T5 type; +}; + +template +struct TupleElement { + typedef T6 type; +}; + +template +struct TupleElement { + typedef T7 type; +}; + +template +struct TupleElement { + typedef T8 type; +}; + +template +struct TupleElement { + typedef T9 type; +}; + +} // namespace gtest_internal + +template <> +class tuple<> { + public: + tuple() {} + tuple(const tuple& /* t */) {} + tuple& operator=(const tuple& /* t */) { return *this; } +}; + +template +class GTEST_1_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {} + + tuple(const tuple& t) : f0_(t.f0_) {} + + template + tuple(const GTEST_1_TUPLE_(U)& t) : f0_(t.f0_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_1_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_1_TUPLE_(U)& t) { + f0_ = t.f0_; + return *this; + } + + T0 f0_; +}; + +template +class GTEST_2_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_() {} + + 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 + tuple(const GTEST_2_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_) {} + template + tuple(const ::std::pair& p) : f0_(p.first), f1_(p.second) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_2_TUPLE_(U)& t) { + return CopyFrom(t); + } + template + tuple& operator=(const ::std::pair& p) { + f0_ = p.first; + f1_ = p.second; + return *this; + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_2_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + return *this; + } + + T0 f0_; + T1 f1_; +}; + +template +class GTEST_3_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_() {} + + 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 + 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 + tuple& operator=(const GTEST_3_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + 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 +class GTEST_4_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_() {} + + 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 + 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 + tuple& operator=(const GTEST_4_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + 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 +class GTEST_5_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_() {} + + 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 + 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 + tuple& operator=(const GTEST_5_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + 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 +class GTEST_6_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_() {} + + 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 + 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 + tuple& operator=(const GTEST_6_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + 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 +class GTEST_7_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_() {} + + 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 + 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 + tuple& operator=(const GTEST_7_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + 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 +class GTEST_8_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_() {} + + 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 + 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 + tuple& operator=(const GTEST_8_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + 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 +class GTEST_9_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_() {} + + 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 + 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 + tuple& operator=(const GTEST_9_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + 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 +class tuple { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_(), + f9_() {} + + 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 + 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 + tuple& operator=(const GTEST_10_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + 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 to make_tuple(). And we don't +// implement tie(). + +inline tuple<> make_tuple() { return tuple<>(); } + +template +inline GTEST_1_TUPLE_(T) make_tuple(const T0& f0) { + return GTEST_1_TUPLE_(T)(f0); +} + +template +inline GTEST_2_TUPLE_(T) make_tuple(const T0& f0, const T1& f1) { + return GTEST_2_TUPLE_(T)(f0, f1); +} + +template +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 +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 +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 +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 +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 +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 +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 +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 struct tuple_size; + +template +struct tuple_size { + static const int value = 0; +}; + +template +struct tuple_size { + static const int value = 1; +}; + +template +struct tuple_size { + static const int value = 2; +}; + +template +struct tuple_size { + static const int value = 3; +}; + +template +struct tuple_size { + static const int value = 4; +}; + +template +struct tuple_size { + static const int value = 5; +}; + +template +struct tuple_size { + static const int value = 6; +}; + +template +struct tuple_size { + static const int value = 7; +}; + +template +struct tuple_size { + static const int value = 8; +}; + +template +struct tuple_size { + static const int value = 9; +}; + +template +struct tuple_size { + static const int value = 10; +}; + +template +struct tuple_element { + typedef typename gtest_internal::TupleElement< + k < (tuple_size::value), k, Tuple>::type type; +}; + +#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element::type + +// 6.1.3.4 Element access. + +namespace gtest_internal { + +template <> +class Get<0> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple)) + Field(Tuple& t) { return t.f0_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple)) + ConstField(const Tuple& t) { return t.f0_; } +}; + +template <> +class Get<1> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple)) + Field(Tuple& t) { return t.f1_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple)) + ConstField(const Tuple& t) { return t.f1_; } +}; + +template <> +class Get<2> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple)) + Field(Tuple& t) { return t.f2_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple)) + ConstField(const Tuple& t) { return t.f2_; } +}; + +template <> +class Get<3> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple)) + Field(Tuple& t) { return t.f3_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple)) + ConstField(const Tuple& t) { return t.f3_; } +}; + +template <> +class Get<4> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple)) + Field(Tuple& t) { return t.f4_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple)) + ConstField(const Tuple& t) { return t.f4_; } +}; + +template <> +class Get<5> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple)) + Field(Tuple& t) { return t.f5_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple)) + ConstField(const Tuple& t) { return t.f5_; } +}; + +template <> +class Get<6> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple)) + Field(Tuple& t) { return t.f6_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple)) + ConstField(const Tuple& t) { return t.f6_; } +}; + +template <> +class Get<7> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple)) + Field(Tuple& t) { return t.f7_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple)) + ConstField(const Tuple& t) { return t.f7_; } +}; + +template <> +class Get<8> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple)) + Field(Tuple& t) { return t.f8_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple)) + ConstField(const Tuple& t) { return t.f8_; } +}; + +template <> +class Get<9> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple)) + Field(Tuple& t) { return t.f9_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple)) + ConstField(const Tuple& t) { return t.f9_; } +}; + +} // namespace gtest_internal + +template +GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T))) +get(GTEST_10_TUPLE_(T)& t) { + return gtest_internal::Get::Field(t); +} + +template +GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T))) +get(const GTEST_10_TUPLE_(T)& t) { + return gtest_internal::Get::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::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 +struct SameSizeTuplePrefixComparator; + +template <> +struct SameSizeTuplePrefixComparator<0, 0> { + template + static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) { + return true; + } +}; + +template +struct SameSizeTuplePrefixComparator { + template + static bool Eq(const Tuple1& t1, const Tuple2& t2) { + return SameSizeTuplePrefixComparator::Eq(t1, t2) && + ::std::tr1::get(t1) == ::std::tr1::get(t2); + } +}; + +} // namespace gtest_internal + +template +inline bool operator==(const GTEST_10_TUPLE_(T)& t, + const GTEST_10_TUPLE_(U)& u) { + return gtest_internal::SameSizeTuplePrefixComparator< + tuple_size::value, + tuple_size::value>::Eq(t, u); +} + +template +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_DECLARE_TUPLE_AS_FRIEND_ +#undef GTEST_BY_REF_ +#undef GTEST_ADD_REF_ +#undef GTEST_TUPLE_ELEMENT_ + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ +# elif GTEST_ENV_HAS_STD_TUPLE_ +# include +// C++11 puts its tuple into the ::std namespace rather than +// ::std::tr1. gtest expects tuple to live in ::std::tr1, so put it there. +// This causes undefined behavior, but supported compilers react in +// the way we intend. +namespace std { +namespace tr1 { +using ::std::get; +using ::std::make_tuple; +using ::std::tuple; +using ::std::tuple_element; +using ::std::tuple_size; +} +} + +# 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 +// work as the copy of STLport distributed with Symbian is incomplete. +// By making sure BOOST_HAS_TR1_TUPLE is undefined, we force Boost to +// use its own tuple implementation. +# ifdef BOOST_HAS_TR1_TUPLE +# undef BOOST_HAS_TR1_TUPLE +# endif // BOOST_HAS_TR1_TUPLE + +// This prevents , which defines +// BOOST_HAS_TR1_TUPLE, from being #included by Boost's . +# define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED +# include + +# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000) +// GCC 4.0+ implements tr1/tuple in the header. This does +// not conform to the TR1 spec, which requires the header to be . + +# if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302 +// Until version 4.3.2, gcc has a bug that causes , +// which is #included by , to not compile when RTTI is +// disabled. _TR1_FUNCTIONAL is the header guard for +// . Hence the following #define is a hack to prevent +// from being included. +# define _TR1_FUNCTIONAL 1 +# include +# undef _TR1_FUNCTIONAL // Allows the user to #include + // if he chooses to. +# else +# include // NOLINT +# endif // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302 + +# else +// If the compiler is not GCC 4.0+, we assume the user is using a +// spec-conforming TR1 implementation. +# include // NOLINT +# endif // GTEST_USE_OWN_TR1_TUPLE + +#endif // GTEST_HAS_TR1_TUPLE + +// Determines whether clone(2) is supported. +// Usually it will only be available on Linux, excluding +// Linux on the Itanium architecture. +// Also see http://linux.die.net/man/2/clone. +#ifndef GTEST_HAS_CLONE +// The user didn't tell us, so we need to figure it out. + +# if GTEST_OS_LINUX && !defined(__ia64__) +# if GTEST_OS_LINUX_ANDROID +// On Android, clone() is only available on ARM starting with Gingerbread. +# if defined(__arm__) && __ANDROID_API__ >= 9 +# define GTEST_HAS_CLONE 1 +# else +# define GTEST_HAS_CLONE 0 +# endif +# else +# define GTEST_HAS_CLONE 1 +# endif +# else +# define GTEST_HAS_CLONE 0 +# endif // GTEST_OS_LINUX && !defined(__ia64__) + +#endif // GTEST_HAS_CLONE + +// Determines whether to support stream redirection. This is used to test +// output correctness and to implement death tests. +#ifndef GTEST_HAS_STREAM_REDIRECTION +// By default, we assume that stream redirection is supported on all +// platforms except known mobile ones. +# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN +# define GTEST_HAS_STREAM_REDIRECTION 0 +# else +# define GTEST_HAS_STREAM_REDIRECTION 1 +# endif // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN +#endif // GTEST_HAS_STREAM_REDIRECTION + +// Determines whether to support death tests. +// Google Test does not support death tests for VC 7.1 and earlier as +// abort() in a VC 7.1 application compiled as GUI in debug config +// pops up a dialog window that cannot be suppressed programmatically. +#if (GTEST_OS_LINUX || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \ + (GTEST_OS_MAC && !GTEST_OS_IOS) || GTEST_OS_IOS_SIMULATOR || \ + (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \ + GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX || \ + GTEST_OS_OPENBSD || GTEST_OS_QNX) +# define GTEST_HAS_DEATH_TEST 1 +# include // NOLINT +#endif + +// We don't support MSVC 7.1 with exceptions disabled now. Therefore +// all the compilers we care about are adequate for supporting +// value-parameterized tests. +#define GTEST_HAS_PARAM_TEST 1 + +// Determines whether to support type-driven tests. + +// Typed tests need and variadic macros, which GCC, VC++ 8.0, +// Sun Pro CC, IBM Visual Age, and HP aCC support. +#if defined(__GNUC__) || (_MSC_VER >= 1400) || defined(__SUNPRO_CC) || \ + defined(__IBMCPP__) || defined(__HP_aCC) +# define GTEST_HAS_TYPED_TEST 1 +# define GTEST_HAS_TYPED_TEST_P 1 +#endif + +// Determines whether to support Combine(). This only makes sense when +// value-parameterized tests are enabled. The implementation doesn't +// work on Sun Studio since it doesn't understand templated conversion +// operators. +#if GTEST_HAS_PARAM_TEST && GTEST_HAS_TR1_TUPLE && !defined(__SUNPRO_CC) +# define GTEST_HAS_COMBINE 1 +#endif + +// Determines whether the system compiler uses UTF-16 for encoding wide strings. +#define GTEST_WIDE_STRING_USES_UTF16_ \ + (GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_SYMBIAN || GTEST_OS_AIX) + +// Determines whether test results can be streamed to a socket. +#if GTEST_OS_LINUX +# define GTEST_CAN_STREAM_RESULTS_ 1 +#endif + +// Defines some utility macros. + +// The GNU compiler emits a warning if nested "if" statements are followed by +// an "else" statement and braces are not used to explicitly disambiguate the +// "else" binding. This leads to problems with code like: +// +// if (gate) +// ASSERT_*(condition) << "Some message"; +// +// The "switch (0) case 0:" idiom is used to suppress this. +#ifdef __INTEL_COMPILER +# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ +#else +# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default: // NOLINT +#endif + +// Use this annotation at the end of a struct/class definition to +// prevent the compiler from optimizing away instances that are never +// used. This is useful when all interesting logic happens inside the +// c'tor and / or d'tor. Example: +// +// struct Foo { +// Foo() { ... } +// } GTEST_ATTRIBUTE_UNUSED_; +// +// Also use it after a variable or parameter declaration to tell the +// compiler the variable/parameter does not have to be used. +#if defined(__GNUC__) && !defined(COMPILER_ICC) +# define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused)) +#else +# define GTEST_ATTRIBUTE_UNUSED_ +#endif + +// A macro to disallow operator= +// This should be used in the private: declarations for a class. +#define GTEST_DISALLOW_ASSIGN_(type)\ + void operator=(type const &) + +// A macro to disallow copy constructor and operator= +// This should be used in the private: declarations for a class. +#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type)\ + type(type const &);\ + GTEST_DISALLOW_ASSIGN_(type) + +// Tell the compiler to warn about unused return values for functions declared +// with this macro. The macro should be used on function declarations +// following the argument list: +// +// Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_; +#if defined(__GNUC__) && (GTEST_GCC_VER_ >= 30400) && !defined(COMPILER_ICC) +# define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result)) +#else +# define GTEST_MUST_USE_RESULT_ +#endif // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC + +// Determine whether the compiler supports Microsoft's Structured Exception +// Handling. This is supported by several Windows compilers but generally +// does not exist on any other system. +#ifndef GTEST_HAS_SEH +// The user didn't tell us, so we need to figure it out. + +# if defined(_MSC_VER) || defined(__BORLANDC__) +// These two compilers are known to support SEH. +# define GTEST_HAS_SEH 1 +# else +// Assume no SEH. +# define GTEST_HAS_SEH 0 +# endif + +#endif // GTEST_HAS_SEH + +#ifdef _MSC_VER + +# if GTEST_LINKED_AS_SHARED_LIBRARY +# define GTEST_API_ __declspec(dllimport) +# elif GTEST_CREATE_SHARED_LIBRARY +# define GTEST_API_ __declspec(dllexport) +# endif + +#endif // _MSC_VER + +#ifndef GTEST_API_ +# define GTEST_API_ +#endif + +#ifdef __GNUC__ +// Ask the compiler to never inline a given function. +# define GTEST_NO_INLINE_ __attribute__((noinline)) +#else +# define GTEST_NO_INLINE_ +#endif + +// _LIBCPP_VERSION is defined by the libc++ library from the LLVM project. +#if defined(__GLIBCXX__) || defined(_LIBCPP_VERSION) +# define GTEST_HAS_CXXABI_H_ 1 +#else +# define GTEST_HAS_CXXABI_H_ 0 +#endif + +namespace testing { + +class Message; + +namespace internal { + +// A secret type that Google Test users don't know about. It has no +// definition on purpose. Therefore it's impossible to create a +// Secret object, which is what we want. +class Secret; + +// The GTEST_COMPILE_ASSERT_ macro can be used to verify that a compile time +// expression is true. For example, you could use it to verify the +// size of a static array: +// +// GTEST_COMPILE_ASSERT_(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES, +// content_type_names_incorrect_size); +// +// or to make sure a struct is smaller than a certain size: +// +// GTEST_COMPILE_ASSERT_(sizeof(foo) < 128, foo_too_large); +// +// The second argument to the macro is the name of the variable. If +// the expression is false, most compilers will issue a warning/error +// containing the name of the variable. + +template +struct CompileAssert { +}; + +#define GTEST_COMPILE_ASSERT_(expr, msg) \ + typedef ::testing::internal::CompileAssert<(static_cast(expr))> \ + msg[static_cast(expr) ? 1 : -1] GTEST_ATTRIBUTE_UNUSED_ + +// Implementation details of GTEST_COMPILE_ASSERT_: +// +// - GTEST_COMPILE_ASSERT_ works by defining an array type that has -1 +// elements (and thus is invalid) when the expression is false. +// +// - The simpler definition +// +// #define GTEST_COMPILE_ASSERT_(expr, msg) typedef char msg[(expr) ? 1 : -1] +// +// does not work, as gcc supports variable-length arrays whose sizes +// are determined at run-time (this is gcc's extension and not part +// of the C++ standard). As a result, gcc fails to reject the +// following code with the simple definition: +// +// int foo; +// GTEST_COMPILE_ASSERT_(foo, msg); // not supposed to compile as foo is +// // not a compile-time constant. +// +// - By using the type CompileAssert<(bool(expr))>, we ensures that +// expr is a compile-time constant. (Template arguments must be +// determined at compile-time.) +// +// - The outter parentheses in CompileAssert<(bool(expr))> are necessary +// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written +// +// CompileAssert +// +// instead, these compilers will refuse to compile +// +// GTEST_COMPILE_ASSERT_(5 > 0, some_message); +// +// (They seem to think the ">" in "5 > 0" marks the end of the +// template argument list.) +// +// - The array size is (bool(expr) ? 1 : -1), instead of simply +// +// ((expr) ? 1 : -1). +// +// This is to avoid running into a bug in MS VC 7.1, which +// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1. + +// StaticAssertTypeEqHelper is used by StaticAssertTypeEq defined in gtest.h. +// +// This template is declared, but intentionally undefined. +template +struct StaticAssertTypeEqHelper; + +template +struct StaticAssertTypeEqHelper {}; + +#if GTEST_HAS_GLOBAL_STRING +typedef ::string string; +#else +typedef ::std::string string; +#endif // GTEST_HAS_GLOBAL_STRING + +#if GTEST_HAS_GLOBAL_WSTRING +typedef ::wstring wstring; +#elif GTEST_HAS_STD_WSTRING +typedef ::std::wstring wstring; +#endif // GTEST_HAS_GLOBAL_WSTRING + +// A helper for suppressing warnings on constant condition. It just +// returns 'condition'. +GTEST_API_ bool IsTrue(bool condition); + +// Defines scoped_ptr. + +// This implementation of scoped_ptr is PARTIAL - it only contains +// enough stuff to satisfy Google Test's need. +template +class scoped_ptr { + public: + typedef T element_type; + + explicit scoped_ptr(T* p = NULL) : ptr_(p) {} + ~scoped_ptr() { reset(); } + + T& operator*() const { return *ptr_; } + T* operator->() const { return ptr_; } + T* get() const { return ptr_; } + + T* release() { + T* const ptr = ptr_; + ptr_ = NULL; + return ptr; + } + + void reset(T* p = NULL) { + if (p != ptr_) { + if (IsTrue(sizeof(T) > 0)) { // Makes sure T is a complete type. + delete ptr_; + } + ptr_ = p; + } + } + + private: + T* ptr_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(scoped_ptr); +}; + +// Defines RE. + +// A simple C++ wrapper for . It uses the POSIX Extended +// Regular Expression syntax. +class GTEST_API_ RE { + public: + // A copy constructor is required by the Standard to initialize object + // references from r-values. + RE(const RE& other) { Init(other.pattern()); } + + // Constructs an RE from a string. + RE(const ::std::string& regex) { Init(regex.c_str()); } // NOLINT + +#if GTEST_HAS_GLOBAL_STRING + + RE(const ::string& regex) { Init(regex.c_str()); } // NOLINT + +#endif // GTEST_HAS_GLOBAL_STRING + + RE(const char* regex) { Init(regex); } // NOLINT + ~RE(); + + // Returns the string representation of the regex. + const char* pattern() const { return pattern_; } + + // FullMatch(str, re) returns true iff regular expression re matches + // the entire str. + // PartialMatch(str, re) returns true iff regular expression re + // matches a substring of str (including str itself). + // + // TODO(wan@google.com): make FullMatch() and PartialMatch() work + // when str contains NUL characters. + static bool FullMatch(const ::std::string& str, const RE& re) { + return FullMatch(str.c_str(), re); + } + static bool PartialMatch(const ::std::string& str, const RE& re) { + return PartialMatch(str.c_str(), re); + } + +#if GTEST_HAS_GLOBAL_STRING + + static bool FullMatch(const ::string& str, const RE& re) { + return FullMatch(str.c_str(), re); + } + static bool PartialMatch(const ::string& str, const RE& re) { + return PartialMatch(str.c_str(), re); + } + +#endif // GTEST_HAS_GLOBAL_STRING + + static bool FullMatch(const char* str, const RE& re); + static bool PartialMatch(const char* str, const RE& re); + + private: + void Init(const char* regex); + + // We use a const char* instead of an std::string, as Google Test used to be + // used where std::string is not available. TODO(wan@google.com): change to + // std::string. + const char* pattern_; + bool is_valid_; + +#if GTEST_USES_POSIX_RE + + regex_t full_regex_; // For FullMatch(). + regex_t partial_regex_; // For PartialMatch(). + +#else // GTEST_USES_SIMPLE_RE + + const char* full_pattern_; // For FullMatch(); + +#endif + + GTEST_DISALLOW_ASSIGN_(RE); +}; + +// Formats a source file path and a line number as they would appear +// in an error message from the compiler used to compile this code. +GTEST_API_ ::std::string FormatFileLocation(const char* file, int line); + +// Formats a file location for compiler-independent XML output. +// Although this function is not platform dependent, we put it next to +// FormatFileLocation in order to contrast the two functions. +GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file, + int line); + +// Defines logging utilities: +// GTEST_LOG_(severity) - logs messages at the specified severity level. The +// message itself is streamed into the macro. +// LogToStderr() - directs all log messages to stderr. +// FlushInfoLog() - flushes informational log messages. + +enum GTestLogSeverity { + GTEST_INFO, + GTEST_WARNING, + GTEST_ERROR, + GTEST_FATAL +}; + +// Formats log entry severity, provides a stream object for streaming the +// log message, and terminates the message with a newline when going out of +// scope. +class GTEST_API_ GTestLog { + public: + GTestLog(GTestLogSeverity severity, const char* file, int line); + + // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. + ~GTestLog(); + + ::std::ostream& GetStream() { return ::std::cerr; } + + private: + const GTestLogSeverity severity_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestLog); +}; + +#define GTEST_LOG_(severity) \ + ::testing::internal::GTestLog(::testing::internal::GTEST_##severity, \ + __FILE__, __LINE__).GetStream() + +inline void LogToStderr() {} +inline void FlushInfoLog() { fflush(NULL); } + +// INTERNAL IMPLEMENTATION - DO NOT USE. +// +// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition +// is not satisfied. +// Synopsys: +// GTEST_CHECK_(boolean_condition); +// or +// GTEST_CHECK_(boolean_condition) << "Additional message"; +// +// This checks the condition and if the condition is not satisfied +// it prints message about the condition violation, including the +// condition itself, plus additional message streamed into it, if any, +// and then it aborts the program. It aborts the program irrespective of +// whether it is built in the debug mode or not. +#define GTEST_CHECK_(condition) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::IsTrue(condition)) \ + ; \ + else \ + GTEST_LOG_(FATAL) << "Condition " #condition " failed. " + +// An all-mode assert to verify that the given POSIX-style function +// call returns 0 (indicating success). Known limitation: this +// doesn't expand to a balanced 'if' statement, so enclose the macro +// in {} if you need to use it as the only statement in an 'if' +// branch. +#define GTEST_CHECK_POSIX_SUCCESS_(posix_call) \ + if (const int gtest_error = (posix_call)) \ + GTEST_LOG_(FATAL) << #posix_call << "failed with error " \ + << gtest_error + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Use ImplicitCast_ as a safe version of static_cast for upcasting in +// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a +// const Foo*). When you use ImplicitCast_, the compiler checks that +// the cast is safe. Such explicit ImplicitCast_s are necessary in +// surprisingly many situations where C++ demands an exact type match +// instead of an argument type convertable to a target type. +// +// The syntax for using ImplicitCast_ is the same as for static_cast: +// +// ImplicitCast_(expr) +// +// ImplicitCast_ would have been part of the C++ standard library, +// but the proposal was submitted too late. It will probably make +// its way into the language in the future. +// +// This relatively ugly name is intentional. It prevents clashes with +// similar functions users may have (e.g., implicit_cast). The internal +// namespace alone is not enough because the function can be found by ADL. +template +inline To ImplicitCast_(To x) { return x; } + +// When you upcast (that is, cast a pointer from type Foo to type +// SuperclassOfFoo), it's fine to use ImplicitCast_<>, since upcasts +// always succeed. When you downcast (that is, cast a pointer from +// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because +// how do you know the pointer is really of type SubclassOfFoo? It +// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus, +// when you downcast, you should use this macro. In debug mode, we +// use dynamic_cast<> to double-check the downcast is legal (we die +// if it's not). In normal mode, we do the efficient static_cast<> +// instead. Thus, it's important to test in debug mode to make sure +// the cast is legal! +// This is the only place in the code we should use dynamic_cast<>. +// In particular, you SHOULDN'T be using dynamic_cast<> in order to +// do RTTI (eg code like this: +// if (dynamic_cast(foo)) HandleASubclass1Object(foo); +// if (dynamic_cast(foo)) HandleASubclass2Object(foo); +// You should design the code some other way not to need this. +// +// This relatively ugly name is intentional. It prevents clashes with +// similar functions users may have (e.g., down_cast). The internal +// namespace alone is not enough because the function can be found by ADL. +template // use like this: DownCast_(foo); +inline To DownCast_(From* f) { // so we only accept pointers + // Ensures that To is a sub-type of From *. This test is here only + // for compile-time type checking, and has no overhead in an + // optimized build at run-time, as it will be optimized away + // completely. + if (false) { + const To to = NULL; + ::testing::internal::ImplicitCast_(to); + } + +#if GTEST_HAS_RTTI + // RTTI: debug mode only! + GTEST_CHECK_(f == NULL || dynamic_cast(f) != NULL); +#endif + return static_cast(f); +} + +// Downcasts the pointer of type Base to Derived. +// Derived must be a subclass of Base. The parameter MUST +// point to a class of type Derived, not any subclass of it. +// When RTTI is available, the function performs a runtime +// check to enforce this. +template +Derived* CheckedDowncastToActualType(Base* base) { +#if GTEST_HAS_RTTI + GTEST_CHECK_(typeid(*base) == typeid(Derived)); + return dynamic_cast(base); // NOLINT +#else + return static_cast(base); // Poor man's downcast. +#endif +} + +#if GTEST_HAS_STREAM_REDIRECTION + +// Defines the stderr capturer: +// CaptureStdout - starts capturing stdout. +// GetCapturedStdout - stops capturing stdout and returns the captured string. +// CaptureStderr - starts capturing stderr. +// GetCapturedStderr - stops capturing stderr and returns the captured string. +// +GTEST_API_ void CaptureStdout(); +GTEST_API_ std::string GetCapturedStdout(); +GTEST_API_ void CaptureStderr(); +GTEST_API_ std::string GetCapturedStderr(); + +#endif // GTEST_HAS_STREAM_REDIRECTION + + +#if GTEST_HAS_DEATH_TEST + +const ::std::vector& GetInjectableArgvs(); +void SetInjectableArgvs(const ::std::vector* + new_argvs); + +// A copy of all command line arguments. Set by InitGoogleTest(). +extern ::std::vector g_argvs; + +#endif // GTEST_HAS_DEATH_TEST + +// Defines synchronization primitives. + +#if GTEST_HAS_PTHREAD + +// Sleeps for (roughly) n milli-seconds. This function is only for +// testing Google Test's own constructs. Don't use it in user tests, +// either directly or indirectly. +inline void SleepMilliseconds(int n) { + const timespec time = { + 0, // 0 seconds. + n * 1000L * 1000L, // And n ms. + }; + nanosleep(&time, NULL); +} + +// Allows a controller thread to pause execution of newly created +// threads until notified. Instances of this class must be created +// and destroyed in the controller thread. +// +// This class is only for testing Google Test's own constructs. Do not +// use it in user tests, either directly or indirectly. +class Notification { + public: + Notification() : notified_(false) { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL)); + } + ~Notification() { + pthread_mutex_destroy(&mutex_); + } + + // Notifies all threads created with this notification to start. Must + // be called from the controller thread. + void Notify() { + pthread_mutex_lock(&mutex_); + notified_ = true; + pthread_mutex_unlock(&mutex_); + } + + // Blocks until the controller thread notifies. Must be called from a test + // thread. + void WaitForNotification() { + for (;;) { + pthread_mutex_lock(&mutex_); + const bool notified = notified_; + pthread_mutex_unlock(&mutex_); + if (notified) + break; + SleepMilliseconds(10); + } + } + + private: + pthread_mutex_t mutex_; + bool notified_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification); +}; + +// As a C-function, ThreadFuncWithCLinkage cannot be templated itself. +// Consequently, it cannot select a correct instantiation of ThreadWithParam +// in order to call its Run(). Introducing ThreadWithParamBase as a +// non-templated base class for ThreadWithParam allows us to bypass this +// problem. +class ThreadWithParamBase { + public: + virtual ~ThreadWithParamBase() {} + virtual void Run() = 0; +}; + +// pthread_create() accepts a pointer to a function type with the C linkage. +// According to the Standard (7.5/1), function types with different linkages +// are different even if they are otherwise identical. Some compilers (for +// example, SunStudio) treat them as different types. Since class methods +// cannot be defined with C-linkage we need to define a free C-function to +// pass into pthread_create(). +extern "C" inline void* ThreadFuncWithCLinkage(void* thread) { + static_cast(thread)->Run(); + return NULL; +} + +// Helper class for testing Google Test's multi-threading constructs. +// To use it, write: +// +// void ThreadFunc(int param) { /* Do things with param */ } +// Notification thread_can_start; +// ... +// // The thread_can_start parameter is optional; you can supply NULL. +// ThreadWithParam thread(&ThreadFunc, 5, &thread_can_start); +// thread_can_start.Notify(); +// +// These classes are only for testing Google Test's own constructs. Do +// not use them in user tests, either directly or indirectly. +template +class ThreadWithParam : public ThreadWithParamBase { + public: + typedef void (*UserThreadFunc)(T); + + ThreadWithParam( + UserThreadFunc func, T param, Notification* thread_can_start) + : func_(func), + param_(param), + thread_can_start_(thread_can_start), + finished_(false) { + ThreadWithParamBase* const base = this; + // The thread can be created only after all fields except thread_ + // have been initialized. + GTEST_CHECK_POSIX_SUCCESS_( + pthread_create(&thread_, 0, &ThreadFuncWithCLinkage, base)); + } + ~ThreadWithParam() { Join(); } + + void Join() { + if (!finished_) { + GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, 0)); + finished_ = true; + } + } + + virtual void Run() { + if (thread_can_start_ != NULL) + thread_can_start_->WaitForNotification(); + func_(param_); + } + + private: + const UserThreadFunc func_; // User-supplied thread function. + const T param_; // User-supplied parameter to the thread function. + // When non-NULL, used to block execution until the controller thread + // notifies. + Notification* const thread_can_start_; + bool finished_; // true iff we know that the thread function has finished. + pthread_t thread_; // The native thread object. + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam); +}; + +// MutexBase and Mutex implement mutex on pthreads-based platforms. They +// are used in conjunction with class MutexLock: +// +// Mutex mutex; +// ... +// MutexLock lock(&mutex); // Acquires the mutex and releases it at the end +// // of the current scope. +// +// MutexBase implements behavior for both statically and dynamically +// allocated mutexes. Do not use MutexBase directly. Instead, write +// the following to define a static mutex: +// +// GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex); +// +// You can forward declare a static mutex like this: +// +// GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex); +// +// To create a dynamic mutex, just define an object of type Mutex. +class MutexBase { + public: + // Acquires this mutex. + void Lock() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_)); + owner_ = pthread_self(); + has_owner_ = true; + } + + // Releases this mutex. + void Unlock() { + // Since the lock is being released the owner_ field should no longer be + // considered valid. We don't protect writing to has_owner_ here, as it's + // the caller's responsibility to ensure that the current thread holds the + // mutex when this is called. + has_owner_ = false; + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_)); + } + + // Does nothing if the current thread holds the mutex. Otherwise, crashes + // with high probability. + void AssertHeld() const { + GTEST_CHECK_(has_owner_ && pthread_equal(owner_, pthread_self())) + << "The current thread is not holding the mutex @" << this; + } + + // A static mutex may be used before main() is entered. It may even + // be used before the dynamic initialization stage. Therefore we + // must be able to initialize a static mutex object at link time. + // This means MutexBase has to be a POD and its member variables + // have to be public. + public: + pthread_mutex_t mutex_; // The underlying pthread mutex. + // has_owner_ indicates whether the owner_ field below contains a valid thread + // ID and is therefore safe to inspect (e.g., to use in pthread_equal()). All + // accesses to the owner_ field should be protected by a check of this field. + // An alternative might be to memset() owner_ to all zeros, but there's no + // guarantee that a zero'd pthread_t is necessarily invalid or even different + // from pthread_self(). + bool has_owner_; + pthread_t owner_; // The thread holding the mutex. +}; + +// Forward-declares a static mutex. +# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ + extern ::testing::internal::MutexBase mutex + +// Defines and statically (i.e. at link time) initializes a static mutex. +// The initialization list here does not explicitly initialize each field, +// instead relying on default initialization for the unspecified fields. In +// particular, the owner_ field (a pthread_t) is not explicitly initialized. +// This allows initialization to work whether pthread_t is a scalar or struct. +// The flag -Wmissing-field-initializers must not be specified for this to work. +# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \ + ::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, false } + +// The Mutex class can only be used for mutexes created at runtime. It +// shares its API with MutexBase otherwise. +class Mutex : public MutexBase { + public: + Mutex() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL)); + has_owner_ = false; + } + ~Mutex() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_)); + } + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex); +}; + +// We cannot name this class MutexLock as the ctor declaration would +// conflict with a macro named MutexLock, which is defined on some +// platforms. Hence the typedef trick below. +class GTestMutexLock { + public: + explicit GTestMutexLock(MutexBase* mutex) + : mutex_(mutex) { mutex_->Lock(); } + + ~GTestMutexLock() { mutex_->Unlock(); } + + private: + MutexBase* const mutex_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock); +}; + +typedef GTestMutexLock MutexLock; + +// Helpers for ThreadLocal. + +// pthread_key_create() requires DeleteThreadLocalValue() to have +// C-linkage. Therefore it cannot be templatized to access +// ThreadLocal. Hence the need for class +// ThreadLocalValueHolderBase. +class ThreadLocalValueHolderBase { + public: + virtual ~ThreadLocalValueHolderBase() {} +}; + +// Called by pthread to delete thread-local data stored by +// pthread_setspecific(). +extern "C" inline void DeleteThreadLocalValue(void* value_holder) { + delete static_cast(value_holder); +} + +// Implements thread-local storage on pthreads-based systems. +// +// // Thread 1 +// ThreadLocal tl(100); // 100 is the default value for each thread. +// +// // Thread 2 +// tl.set(150); // Changes the value for thread 2 only. +// EXPECT_EQ(150, tl.get()); +// +// // Thread 1 +// EXPECT_EQ(100, tl.get()); // In thread 1, tl has the original value. +// tl.set(200); +// EXPECT_EQ(200, tl.get()); +// +// The template type argument T must have a public copy constructor. +// In addition, the default ThreadLocal constructor requires T to have +// a public default constructor. +// +// An object managed for a thread by a ThreadLocal instance is deleted +// when the thread exits. Or, if the ThreadLocal instance dies in +// that thread, when the ThreadLocal dies. It's the user's +// responsibility to ensure that all other threads using a ThreadLocal +// have exited when it dies, or the per-thread objects for those +// threads will not be deleted. +// +// Google Test only uses global ThreadLocal objects. That means they +// will die after main() has returned. Therefore, no per-thread +// object managed by Google Test will be leaked as long as all threads +// using Google Test have exited when main() returns. +template +class ThreadLocal { + public: + ThreadLocal() : key_(CreateKey()), + default_() {} + explicit ThreadLocal(const T& value) : key_(CreateKey()), + default_(value) {} + + ~ThreadLocal() { + // Destroys the managed object for the current thread, if any. + DeleteThreadLocalValue(pthread_getspecific(key_)); + + // Releases resources associated with the key. This will *not* + // delete managed objects for other threads. + GTEST_CHECK_POSIX_SUCCESS_(pthread_key_delete(key_)); + } + + T* pointer() { return GetOrCreateValue(); } + const T* pointer() const { return GetOrCreateValue(); } + const T& get() const { return *pointer(); } + void set(const T& value) { *pointer() = value; } + + private: + // Holds a value of type T. + class ValueHolder : public ThreadLocalValueHolderBase { + public: + explicit ValueHolder(const T& value) : value_(value) {} + + T* pointer() { return &value_; } + + private: + T value_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder); + }; + + static pthread_key_t CreateKey() { + pthread_key_t key; + // When a thread exits, DeleteThreadLocalValue() will be called on + // the object managed for that thread. + GTEST_CHECK_POSIX_SUCCESS_( + pthread_key_create(&key, &DeleteThreadLocalValue)); + return key; + } + + T* GetOrCreateValue() const { + ThreadLocalValueHolderBase* const holder = + static_cast(pthread_getspecific(key_)); + if (holder != NULL) { + return CheckedDowncastToActualType(holder)->pointer(); + } + + ValueHolder* const new_holder = new ValueHolder(default_); + ThreadLocalValueHolderBase* const holder_base = new_holder; + GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, holder_base)); + return new_holder->pointer(); + } + + // A key pthreads uses for looking up per-thread values. + const pthread_key_t key_; + const T default_; // The default value for each thread. + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal); +}; + +# define GTEST_IS_THREADSAFE 1 + +#else // GTEST_HAS_PTHREAD + +// A dummy implementation of synchronization primitives (mutex, lock, +// and thread-local variable). Necessary for compiling Google Test where +// mutex is not supported - using Google Test in multiple threads is not +// supported on such platforms. + +class Mutex { + public: + Mutex() {} + void Lock() {} + void Unlock() {} + void AssertHeld() const {} +}; + +# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ + extern ::testing::internal::Mutex mutex + +# define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex + +class GTestMutexLock { + public: + explicit GTestMutexLock(Mutex*) {} // NOLINT +}; + +typedef GTestMutexLock MutexLock; + +template +class ThreadLocal { + public: + ThreadLocal() : value_() {} + explicit ThreadLocal(const T& value) : value_(value) {} + T* pointer() { return &value_; } + const T* pointer() const { return &value_; } + const T& get() const { return value_; } + void set(const T& value) { value_ = value; } + private: + T value_; +}; + +// The above synchronization primitives have dummy implementations. +// Therefore Google Test is not thread-safe. +# define GTEST_IS_THREADSAFE 0 + +#endif // GTEST_HAS_PTHREAD + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +GTEST_API_ size_t GetThreadCount(); + +// Passing non-POD classes through ellipsis (...) crashes the ARM +// compiler and generates a warning in Sun Studio. The Nokia Symbian +// and the IBM XL C/C++ compiler try to instantiate a copy constructor +// for objects passed through ellipsis (...), failing for uncopyable +// objects. We define this to ensure that only POD is passed through +// ellipsis on these systems. +#if defined(__SYMBIAN32__) || defined(__IBMCPP__) || defined(__SUNPRO_CC) +// We lose support for NULL detection where the compiler doesn't like +// passing non-POD classes through ellipsis (...). +# define GTEST_ELLIPSIS_NEEDS_POD_ 1 +#else +# define GTEST_CAN_COMPARE_NULL 1 +#endif + +// The Nokia Symbian and IBM XL C/C++ compilers cannot decide between +// const T& and const T* in a function template. These compilers +// _can_ decide between class template specializations for T and T*, +// so a tr1::type_traits-like is_pointer works. +#if defined(__SYMBIAN32__) || defined(__IBMCPP__) +# define GTEST_NEEDS_IS_POINTER_ 1 +#endif + +template +struct bool_constant { + typedef bool_constant type; + static const bool value = bool_value; +}; +template const bool bool_constant::value; + +typedef bool_constant false_type; +typedef bool_constant true_type; + +template +struct is_pointer : public false_type {}; + +template +struct is_pointer : public true_type {}; + +template +struct IteratorTraits { + typedef typename Iterator::value_type value_type; +}; + +template +struct IteratorTraits { + typedef T value_type; +}; + +template +struct IteratorTraits { + typedef T value_type; +}; + +#if GTEST_OS_WINDOWS +# define GTEST_PATH_SEP_ "\\" +# define GTEST_HAS_ALT_PATH_SEP_ 1 +// The biggest signed integer type the compiler supports. +typedef __int64 BiggestInt; +#else +# define GTEST_PATH_SEP_ "/" +# define GTEST_HAS_ALT_PATH_SEP_ 0 +typedef long long BiggestInt; // NOLINT +#endif // GTEST_OS_WINDOWS + +// Utilities for char. + +// isspace(int ch) and friends accept an unsigned char or EOF. char +// may be signed, depending on the compiler (or compiler flags). +// Therefore we need to cast a char to unsigned char before calling +// isspace(), etc. + +inline bool IsAlpha(char ch) { + return isalpha(static_cast(ch)) != 0; +} +inline bool IsAlNum(char ch) { + return isalnum(static_cast(ch)) != 0; +} +inline bool IsDigit(char ch) { + return isdigit(static_cast(ch)) != 0; +} +inline bool IsLower(char ch) { + return islower(static_cast(ch)) != 0; +} +inline bool IsSpace(char ch) { + return isspace(static_cast(ch)) != 0; +} +inline bool IsUpper(char ch) { + return isupper(static_cast(ch)) != 0; +} +inline bool IsXDigit(char ch) { + return isxdigit(static_cast(ch)) != 0; +} +inline bool IsXDigit(wchar_t ch) { + const unsigned char low_byte = static_cast(ch); + return ch == low_byte && isxdigit(low_byte) != 0; +} + +inline char ToLower(char ch) { + return static_cast(tolower(static_cast(ch))); +} +inline char ToUpper(char ch) { + return static_cast(toupper(static_cast(ch))); +} + +// The testing::internal::posix namespace holds wrappers for common +// POSIX functions. These wrappers hide the differences between +// Windows/MSVC and POSIX systems. Since some compilers define these +// standard functions as macros, the wrapper cannot have the same name +// as the wrapped function. + +namespace posix { + +// Functions with a different name on Windows. + +#if GTEST_OS_WINDOWS + +typedef struct _stat StatStruct; + +# ifdef __BORLANDC__ +inline int IsATTY(int fd) { return isatty(fd); } +inline int StrCaseCmp(const char* s1, const char* s2) { + return stricmp(s1, s2); +} +inline char* StrDup(const char* src) { return strdup(src); } +# else // !__BORLANDC__ +# if GTEST_OS_WINDOWS_MOBILE +inline int IsATTY(int /* fd */) { return 0; } +# else +inline int IsATTY(int fd) { return _isatty(fd); } +# endif // GTEST_OS_WINDOWS_MOBILE +inline int StrCaseCmp(const char* s1, const char* s2) { + return _stricmp(s1, s2); +} +inline char* StrDup(const char* src) { return _strdup(src); } +# endif // __BORLANDC__ + +# if GTEST_OS_WINDOWS_MOBILE +inline int FileNo(FILE* file) { return reinterpret_cast(_fileno(file)); } +// Stat(), RmDir(), and IsDir() are not needed on Windows CE at this +// time and thus not defined there. +# else +inline int FileNo(FILE* file) { return _fileno(file); } +inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); } +inline int RmDir(const char* dir) { return _rmdir(dir); } +inline bool IsDir(const StatStruct& st) { + return (_S_IFDIR & st.st_mode) != 0; +} +# endif // GTEST_OS_WINDOWS_MOBILE + +#else + +typedef struct stat StatStruct; + +inline int FileNo(FILE* file) { return fileno(file); } +inline int IsATTY(int fd) { return isatty(fd); } +inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); } +inline int StrCaseCmp(const char* s1, const char* s2) { + return strcasecmp(s1, s2); +} +inline char* StrDup(const char* src) { return strdup(src); } +inline int RmDir(const char* dir) { return rmdir(dir); } +inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); } + +#endif // GTEST_OS_WINDOWS + +// Functions deprecated by MSVC 8.0. + +#ifdef _MSC_VER +// Temporarily disable warning 4996 (deprecated function). +# pragma warning(push) +# pragma warning(disable:4996) +#endif + +inline const char* StrNCpy(char* dest, const char* src, size_t n) { + return strncpy(dest, src, n); +} + +// ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and +// StrError() aren't needed on Windows CE at this time and thus not +// defined there. + +#if !GTEST_OS_WINDOWS_MOBILE +inline int ChDir(const char* dir) { return chdir(dir); } +#endif +inline FILE* FOpen(const char* path, const char* mode) { + return fopen(path, mode); +} +#if !GTEST_OS_WINDOWS_MOBILE +inline FILE *FReopen(const char* path, const char* mode, FILE* stream) { + return freopen(path, mode, stream); +} +inline FILE* FDOpen(int fd, const char* mode) { return fdopen(fd, mode); } +#endif +inline int FClose(FILE* fp) { return fclose(fp); } +#if !GTEST_OS_WINDOWS_MOBILE +inline int Read(int fd, void* buf, unsigned int count) { + return static_cast(read(fd, buf, count)); +} +inline int Write(int fd, const void* buf, unsigned int count) { + return static_cast(write(fd, buf, count)); +} +inline int Close(int fd) { return close(fd); } +inline const char* StrError(int errnum) { return strerror(errnum); } +#endif +inline const char* GetEnv(const char* name) { +#if GTEST_OS_WINDOWS_MOBILE + // We are on Windows CE, which has no environment variables. + return NULL; +#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9) + // Environment variables which we programmatically clear will be set to the + // empty string rather than unset (NULL). Handle that case. + const char* const env = getenv(name); + return (env != NULL && env[0] != '\0') ? env : NULL; +#else + return getenv(name); +#endif +} + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif + +#if GTEST_OS_WINDOWS_MOBILE +// Windows CE has no C library. The abort() function is used in +// several places in Google Test. This implementation provides a reasonable +// imitation of standard behaviour. +void Abort(); +#else +inline void Abort() { abort(); } +#endif // GTEST_OS_WINDOWS_MOBILE + +} // namespace posix + +// MSVC "deprecates" snprintf and issues warnings wherever it is used. In +// order to avoid these warnings, we need to use _snprintf or _snprintf_s on +// MSVC-based platforms. We map the GTEST_SNPRINTF_ macro to the appropriate +// function in order to achieve that. We use macro definition here because +// snprintf is a variadic function. +#if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE +// MSVC 2005 and above support variadic macros. +# define GTEST_SNPRINTF_(buffer, size, format, ...) \ + _snprintf_s(buffer, size, size, format, __VA_ARGS__) +#elif defined(_MSC_VER) +// Windows CE does not define _snprintf_s and MSVC prior to 2005 doesn't +// complain about _snprintf. +# define GTEST_SNPRINTF_ _snprintf +#else +# define GTEST_SNPRINTF_ snprintf +#endif + +// The maximum number a BiggestInt can represent. This definition +// works no matter BiggestInt is represented in one's complement or +// two's complement. +// +// We cannot rely on numeric_limits in STL, as __int64 and long long +// are not part of standard C++ and numeric_limits doesn't need to be +// defined for them. +const BiggestInt kMaxBiggestInt = + ~(static_cast(1) << (8*sizeof(BiggestInt) - 1)); + +// This template class serves as a compile-time function from size to +// type. It maps a size in bytes to a primitive type with that +// size. e.g. +// +// TypeWithSize<4>::UInt +// +// is typedef-ed to be unsigned int (unsigned integer made up of 4 +// bytes). +// +// Such functionality should belong to STL, but I cannot find it +// there. +// +// Google Test uses this class in the implementation of floating-point +// comparison. +// +// For now it only handles UInt (unsigned int) as that's all Google Test +// needs. Other types can be easily added in the future if need +// arises. +template +class TypeWithSize { + public: + // This prevents the user from using TypeWithSize with incorrect + // values of N. + typedef void UInt; +}; + +// The specialization for size 4. +template <> +class TypeWithSize<4> { + public: + // unsigned int has size 4 in both gcc and MSVC. + // + // As base/basictypes.h doesn't compile on Windows, we cannot use + // uint32, uint64, and etc here. + typedef int Int; + typedef unsigned int UInt; +}; + +// The specialization for size 8. +template <> +class TypeWithSize<8> { + public: +#if GTEST_OS_WINDOWS + typedef __int64 Int; + typedef unsigned __int64 UInt; +#else + typedef long long Int; // NOLINT + typedef unsigned long long UInt; // NOLINT +#endif // GTEST_OS_WINDOWS +}; + +// Integer types of known sizes. +typedef TypeWithSize<4>::Int Int32; +typedef TypeWithSize<4>::UInt UInt32; +typedef TypeWithSize<8>::Int Int64; +typedef TypeWithSize<8>::UInt UInt64; +typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds. + +// Utilities for command line flags and environment variables. + +// Macro for referencing flags. +#define GTEST_FLAG(name) FLAGS_gtest_##name + +// Macros for declaring flags. +#define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name) +#define GTEST_DECLARE_int32_(name) \ + GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name) +#define GTEST_DECLARE_string_(name) \ + GTEST_API_ extern ::std::string GTEST_FLAG(name) + +// Macros for defining flags. +#define GTEST_DEFINE_bool_(name, default_val, doc) \ + GTEST_API_ bool GTEST_FLAG(name) = (default_val) +#define GTEST_DEFINE_int32_(name, default_val, doc) \ + GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val) +#define GTEST_DEFINE_string_(name, default_val, doc) \ + GTEST_API_ ::std::string GTEST_FLAG(name) = (default_val) + +// Thread annotations +#define GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks) +#define GTEST_LOCK_EXCLUDED_(locks) + +// Parses 'str' for a 32-bit signed integer. If successful, writes the result +// to *value and returns true; otherwise leaves *value unchanged and returns +// false. +// TODO(chandlerc): Find a better way to refactor flag and environment parsing +// out of both gtest-port.cc and gtest.cc to avoid exporting this utility +// function. +bool ParseInt32(const Message& src_text, const char* str, Int32* value); + +// Parses a bool/Int32/string from the environment variable +// corresponding to the given Google Test flag. +bool BoolFromGTestEnv(const char* flag, bool default_val); +GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val); +const char* StringFromGTestEnv(const char* flag, const char* default_val); + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ + +#if GTEST_OS_LINUX +# include +# include +# include +# include +#endif // GTEST_OS_LINUX + +#if GTEST_HAS_EXCEPTIONS +# include +#endif + +#include +#include +#include +#include +#include +#include + +// 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 +// 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) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines the Message class. +// +// IMPORTANT NOTE: Due to limitation of the C++ language, we have to +// leave some internal implementation details in this header file. +// They are clearly marked by comments like this: +// +// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +// +// Such code is NOT meant to be used by a user directly, and is subject +// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user +// program! + +#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ +#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ + +#include + + +// Ensures that there is at least one operator<< in the global namespace. +// See Message& operator<<(...) below for why. +void operator<<(const testing::internal::Secret&, int); + +namespace testing { + +// The Message class works like an ostream repeater. +// +// Typical usage: +// +// 1. You stream a bunch of values to a Message object. +// It will remember the text in a stringstream. +// 2. Then you stream the Message object to an ostream. +// This causes the text in the Message to be streamed +// to the ostream. +// +// For example; +// +// testing::Message foo; +// foo << 1 << " != " << 2; +// std::cout << foo; +// +// will print "1 != 2". +// +// Message is not intended to be inherited from. In particular, its +// destructor is not virtual. +// +// Note that stringstream behaves differently in gcc and in MSVC. You +// can stream a NULL char pointer to it in the former, but not in the +// latter (it causes an access violation if you do). The Message +// class hides this difference by treating a NULL char pointer as +// "(null)". +class GTEST_API_ Message { + private: + // The type of basic IO manipulators (endl, ends, and flush) for + // narrow streams. + typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&); + + public: + // Constructs an empty Message. + Message(); + + // Copy constructor. + Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT + *ss_ << msg.GetString(); + } + + // Constructs a Message from a C-string. + explicit Message(const char* str) : ss_(new ::std::stringstream) { + *ss_ << str; + } + +#if GTEST_OS_SYMBIAN + // Streams a value (either a pointer or not) to this object. + template + inline Message& operator <<(const T& value) { + StreamHelper(typename internal::is_pointer::type(), value); + return *this; + } +#else + // Streams a non-pointer value to this object. + template + inline Message& operator <<(const T& val) { + // Some libraries overload << for STL containers. These + // overloads are defined in the global namespace instead of ::std. + // + // C++'s symbol lookup rule (i.e. Koenig lookup) says that these + // overloads are visible in either the std namespace or the global + // namespace, but not other namespaces, including the testing + // namespace which Google Test's Message class is in. + // + // To allow STL containers (and other types that has a << operator + // defined in the global namespace) to be used in Google Test + // assertions, testing::Message must access the custom << operator + // from the global namespace. With this using declaration, + // overloads of << defined in the global namespace and those + // visible via Koenig lookup are both exposed in this function. + using ::operator <<; + *ss_ << val; + return *this; + } + + // Streams a pointer value to this object. + // + // This function is an overload of the previous one. When you + // stream a pointer to a Message, this definition will be used as it + // is more specialized. (The C++ Standard, section + // [temp.func.order].) If you stream a non-pointer, then the + // previous definition will be used. + // + // The reason for this overload is that streaming a NULL pointer to + // ostream is undefined behavior. Depending on the compiler, you + // may get "0", "(nil)", "(null)", or an access violation. To + // ensure consistent result across compilers, we always treat NULL + // as "(null)". + template + inline Message& operator <<(T* const& pointer) { // NOLINT + if (pointer == NULL) { + *ss_ << "(null)"; + } else { + *ss_ << pointer; + } + return *this; + } +#endif // GTEST_OS_SYMBIAN + + // Since the basic IO manipulators are overloaded for both narrow + // and wide streams, we have to provide this specialized definition + // of operator <<, even though its body is the same as the + // templatized version above. Without this definition, streaming + // endl or other basic IO manipulators to Message will confuse the + // compiler. + Message& operator <<(BasicNarrowIoManip val) { + *ss_ << val; + return *this; + } + + // Instead of 1/0, we want to see true/false for bool values. + Message& operator <<(bool b) { + return *this << (b ? "true" : "false"); + } + + // These two overloads allow streaming a wide C string to a Message + // using the UTF-8 encoding. + Message& operator <<(const wchar_t* wide_c_str); + Message& operator <<(wchar_t* wide_c_str); + +#if GTEST_HAS_STD_WSTRING + // Converts the given wide string to a narrow string using the UTF-8 + // encoding, and streams the result to this Message object. + Message& operator <<(const ::std::wstring& wstr); +#endif // GTEST_HAS_STD_WSTRING + +#if GTEST_HAS_GLOBAL_WSTRING + // Converts the given wide string to a narrow string using the UTF-8 + // encoding, and streams the result to this Message object. + Message& operator <<(const ::wstring& wstr); +#endif // GTEST_HAS_GLOBAL_WSTRING + + // Gets the text streamed to this object so far as an std::string. + // Each '\0' character in the buffer is replaced with "\\0". + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + std::string GetString() const; + + private: + +#if GTEST_OS_SYMBIAN + // These are needed as the Nokia Symbian Compiler cannot decide between + // const T& and const T* in a function template. The Nokia compiler _can_ + // decide between class template specializations for T and T*, so a + // tr1::type_traits-like is_pointer works, and we can overload on that. + template + inline void StreamHelper(internal::true_type /*is_pointer*/, T* pointer) { + if (pointer == NULL) { + *ss_ << "(null)"; + } else { + *ss_ << pointer; + } + } + template + inline void StreamHelper(internal::false_type /*is_pointer*/, + const T& value) { + // See the comments in Message& operator <<(const T&) above for why + // we need this using statement. + using ::operator <<; + *ss_ << value; + } +#endif // GTEST_OS_SYMBIAN + + // We'll hold the text streamed to this object here. + const internal::scoped_ptr< ::std::stringstream> ss_; + + // We declare (but don't implement) this to prevent the compiler + // from implementing the assignment operator. + void operator=(const Message&); +}; + +// Streams a Message to an ostream. +inline std::ostream& operator <<(std::ostream& os, const Message& sb) { + return os << sb.GetString(); +} + +namespace internal { + +// Converts a streamable value to an std::string. A NULL pointer is +// converted to "(null)". When the input value is a ::string, +// ::std::string, ::wstring, or ::std::wstring object, each NUL +// character in it is replaced with "\\0". +template +std::string StreamableToString(const T& streamable) { + return (Message() << streamable).GetString(); +} + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ +// 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 +// 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. +// +// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file declares the String class and functions used internally by +// Google Test. They are subject to change without notice. They should not used +// by code external to Google Test. +// +// This header file is #included by . +// It should not be #included by other files. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ + +#ifdef __BORLANDC__ +// string.h is not guaranteed to provide strcpy on C++ Builder. +# include +#endif + +#include +#include + + +namespace testing { +namespace internal { + +// String - an abstract class holding static string utilities. +class GTEST_API_ String { + public: + // Static utility methods + + // Clones a 0-terminated C string, allocating memory using new. The + // caller is responsible for deleting the return value using + // delete[]. Returns the cloned string, or NULL if the input is + // NULL. + // + // This is different from strdup() in string.h, which allocates + // memory using malloc(). + static const char* CloneCString(const char* c_str); + +#if GTEST_OS_WINDOWS_MOBILE + // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be + // able to pass strings to Win32 APIs on CE we need to convert them + // to 'Unicode', UTF-16. + + // Creates a UTF-16 wide string from the given ANSI string, allocating + // memory using new. The caller is responsible for deleting the return + // value using delete[]. Returns the wide string, or NULL if the + // input is NULL. + // + // The wide string is created using the ANSI codepage (CP_ACP) to + // match the behaviour of the ANSI versions of Win32 calls and the + // C runtime. + static LPCWSTR AnsiToUtf16(const char* c_str); + + // Creates an ANSI string from the given wide string, allocating + // memory using new. The caller is responsible for deleting the return + // value using delete[]. Returns the ANSI string, or NULL if the + // input is NULL. + // + // The returned string is created using the ANSI codepage (CP_ACP) to + // match the behaviour of the ANSI versions of Win32 calls and the + // C runtime. + static const char* Utf16ToAnsi(LPCWSTR utf16_str); +#endif + + // Compares two C strings. Returns true iff they have the same content. + // + // Unlike strcmp(), this function can handle NULL argument(s). A + // NULL C string is considered different to any non-NULL C string, + // including the empty string. + static bool CStringEquals(const char* lhs, const char* rhs); + + // Converts a wide C string to a String using the UTF-8 encoding. + // NULL will be converted to "(null)". If an error occurred during + // the conversion, "(failed to convert from wide string)" is + // returned. + static std::string ShowWideCString(const wchar_t* wide_c_str); + + // Compares two wide C strings. Returns true iff they have the same + // content. + // + // Unlike wcscmp(), this function can handle NULL argument(s). A + // NULL C string is considered different to any non-NULL C string, + // including the empty string. + static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs); + + // Compares two C strings, ignoring case. Returns true iff they + // have the same content. + // + // Unlike strcasecmp(), this function can handle NULL argument(s). + // A NULL C string is considered different to any non-NULL C string, + // including the empty string. + static bool CaseInsensitiveCStringEquals(const char* lhs, + const char* rhs); + + // Compares two wide C strings, ignoring case. Returns true iff they + // have the same content. + // + // Unlike wcscasecmp(), this function can handle NULL argument(s). + // A NULL C string is considered different to any non-NULL wide C string, + // including the empty string. + // NB: The implementations on different platforms slightly differ. + // On windows, this method uses _wcsicmp which compares according to LC_CTYPE + // environment variable. On GNU platform this method uses wcscasecmp + // which compares according to LC_CTYPE category of the current locale. + // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the + // current locale. + static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs, + const wchar_t* rhs); + + // Returns true iff the given string ends with the given suffix, ignoring + // case. Any string is considered to end with an empty suffix. + static bool EndsWithCaseInsensitive( + const std::string& str, const std::string& suffix); + + // Formats an int value as "%02d". + static std::string FormatIntWidth2(int value); // "%02d" for width == 2 + + // Formats an int value as "%X". + static std::string FormatHexInt(int value); + + // Formats a byte as "%02X". + static std::string FormatByte(unsigned char value); + + private: + String(); // Not meant to be instantiated. +}; // class String + +// Gets the content of the stringstream's buffer as an std::string. Each '\0' +// character in the buffer is replaced with "\\0". +GTEST_API_ std::string StringStreamToString(::std::stringstream* stream); + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ +// Copyright 2008, 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: keith.ray@gmail.com (Keith Ray) +// +// Google Test filepath utilities +// +// This header file declares classes and functions used internally by +// Google Test. They are subject to change without notice. +// +// This file is #included in . +// Do not include this header file separately! + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ + + +namespace testing { +namespace internal { + +// FilePath - a class for file and directory pathname manipulation which +// handles platform-specific conventions (like the pathname separator). +// Used for helper functions for naming files in a directory for xml output. +// Except for Set methods, all methods are const or static, which provides an +// "immutable value object" -- useful for peace of mind. +// A FilePath with a value ending in a path separator ("like/this/") represents +// a directory, otherwise it is assumed to represent a file. In either case, +// it may or may not represent an actual file or directory in the file system. +// Names are NOT checked for syntax correctness -- no checking for illegal +// characters, malformed paths, etc. + +class GTEST_API_ FilePath { + public: + FilePath() : pathname_("") { } + FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { } + + explicit FilePath(const std::string& pathname) : pathname_(pathname) { + Normalize(); + } + + FilePath& operator=(const FilePath& rhs) { + Set(rhs); + return *this; + } + + void Set(const FilePath& rhs) { + pathname_ = rhs.pathname_; + } + + const std::string& string() const { return pathname_; } + const char* c_str() const { return pathname_.c_str(); } + + // Returns the current working directory, or "" if unsuccessful. + static FilePath GetCurrentDir(); + + // Given directory = "dir", base_name = "test", number = 0, + // extension = "xml", returns "dir/test.xml". If number is greater + // than zero (e.g., 12), returns "dir/test_12.xml". + // On Windows platform, uses \ as the separator rather than /. + static FilePath MakeFileName(const FilePath& directory, + const FilePath& base_name, + int number, + const char* extension); + + // Given directory = "dir", relative_path = "test.xml", + // returns "dir/test.xml". + // On Windows, uses \ as the separator rather than /. + static FilePath ConcatPaths(const FilePath& directory, + const FilePath& relative_path); + + // Returns a pathname for a file that does not currently exist. The pathname + // will be directory/base_name.extension or + // directory/base_name_.extension if directory/base_name.extension + // already exists. The number will be incremented until a pathname is found + // that does not already exist. + // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. + // There could be a race condition if two or more processes are calling this + // function at the same time -- they could both pick the same filename. + static FilePath GenerateUniqueFileName(const FilePath& directory, + const FilePath& base_name, + const char* extension); + + // Returns true iff the path is "". + bool IsEmpty() const { return pathname_.empty(); } + + // If input name has a trailing separator character, removes it and returns + // the name, otherwise return the name string unmodified. + // On Windows platform, uses \ as the separator, other platforms use /. + FilePath RemoveTrailingPathSeparator() const; + + // Returns a copy of the FilePath with the directory part removed. + // Example: FilePath("path/to/file").RemoveDirectoryName() returns + // FilePath("file"). If there is no directory part ("just_a_file"), it returns + // the FilePath unmodified. If there is no file part ("just_a_dir/") it + // returns an empty FilePath (""). + // On Windows platform, '\' is the path separator, otherwise it is '/'. + FilePath RemoveDirectoryName() const; + + // RemoveFileName returns the directory path with the filename removed. + // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". + // If the FilePath is "a_file" or "/a_file", RemoveFileName returns + // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does + // not have a file, like "just/a/dir/", it returns the FilePath unmodified. + // On Windows platform, '\' is the path separator, otherwise it is '/'. + FilePath RemoveFileName() const; + + // Returns a copy of the FilePath with the case-insensitive extension removed. + // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns + // FilePath("dir/file"). If a case-insensitive extension is not + // found, returns a copy of the original FilePath. + FilePath RemoveExtension(const char* extension) const; + + // Creates directories so that path exists. Returns true if successful or if + // the directories already exist; returns false if unable to create + // directories for any reason. Will also return false if the FilePath does + // not represent a directory (that is, it doesn't end with a path separator). + bool CreateDirectoriesRecursively() const; + + // Create the directory so that path exists. Returns true if successful or + // if the directory already exists; returns false if unable to create the + // directory for any reason, including if the parent directory does not + // exist. Not named "CreateDirectory" because that's a macro on Windows. + bool CreateFolder() const; + + // Returns true if FilePath describes something in the file-system, + // either a file, directory, or whatever, and that something exists. + bool FileOrDirectoryExists() const; + + // Returns true if pathname describes a directory in the file-system + // that exists. + bool DirectoryExists() const; + + // Returns true if FilePath ends with a path separator, which indicates that + // it is intended to represent a directory. Returns false otherwise. + // This does NOT check that a directory (or file) actually exists. + bool IsDirectory() const; + + // Returns true if pathname describes a root directory. (Windows has one + // root directory per disk drive.) + bool IsRootDirectory() const; + + // Returns true if pathname describes an absolute path. + bool IsAbsolutePath() const; + + private: + // Replaces multiple consecutive separators with a single separator. + // For example, "bar///foo" becomes "bar/foo". Does not eliminate other + // redundancies that might be in a pathname involving "." or "..". + // + // A pathname with multiple consecutive separators may occur either through + // user error or as a result of some scripts or APIs that generate a pathname + // with a trailing separator. On other platforms the same API or script + // may NOT generate a pathname with a trailing "/". Then elsewhere that + // pathname may have another "/" and pathname components added to it, + // without checking for the separator already being there. + // The script language and operating system may allow paths like "foo//bar" + // but some of the functions in FilePath will not handle that correctly. In + // particular, RemoveTrailingPathSeparator() only removes one separator, and + // it is called in CreateDirectoriesRecursively() assuming that it will change + // a pathname from directory syntax (trailing separator) to filename syntax. + // + // On Windows this method also replaces the alternate path separator '/' with + // the primary path separator '\\', so that for example "bar\\/\\foo" becomes + // "bar\\foo". + + void Normalize(); + + // Returns a pointer to the last occurence of a valid path separator in + // the FilePath. On Windows, for example, both '/' and '\' are valid path + // separators. Returns NULL if no path separator was found. + const char* FindLastPathSeparator() const; + + std::string pathname_; +}; // class FilePath + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ +// This file was GENERATED by command: +// pump.py gtest-type-util.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2008 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) + +// Type utilities needed for implementing typed and type-parameterized +// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND! +// +// Currently we support at most 50 types in a list, and at most 50 +// type-parameterized tests in one type-parameterized test case. +// Please contact googletestframework@googlegroups.com if you need +// more. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ + + +// #ifdef __GNUC__ is too general here. It is possible to use gcc without using +// libstdc++ (which is where cxxabi.h comes from). +# if GTEST_HAS_CXXABI_H_ +# include +# elif defined(__HP_aCC) +# include +# endif // GTEST_HASH_CXXABI_H_ + +namespace testing { +namespace internal { + +// GetTypeName() returns a human-readable name of type T. +// NB: This function is also used in Google Mock, so don't move it inside of +// the typed-test-only section below. +template +std::string GetTypeName() { +# if GTEST_HAS_RTTI + + const char* const name = typeid(T).name(); +# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC) + int status = 0; + // gcc's implementation of typeid(T).name() mangles the type name, + // so we have to demangle it. +# if GTEST_HAS_CXXABI_H_ + using abi::__cxa_demangle; +# endif // GTEST_HAS_CXXABI_H_ + char* const readable_name = __cxa_demangle(name, 0, 0, &status); + const std::string name_str(status == 0 ? readable_name : name); + free(readable_name); + return name_str; +# else + return name; +# endif // GTEST_HAS_CXXABI_H_ || __HP_aCC + +# else + + return ""; + +# endif // GTEST_HAS_RTTI +} + +#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +// AssertyTypeEq::type is defined iff T1 and T2 are the same +// type. This can be used as a compile-time assertion to ensure that +// two types are equal. + +template +struct AssertTypeEq; + +template +struct AssertTypeEq { + typedef bool type; +}; + +// A unique type used as the default value for the arguments of class +// template Types. This allows us to simulate variadic templates +// (e.g. Types, Type, and etc), which C++ doesn't +// support directly. +struct None {}; + +// The following family of struct and struct templates are used to +// represent type lists. In particular, TypesN +// represents a type list with N types (T1, T2, ..., and TN) in it. +// Except for Types0, every struct in the family has two member types: +// Head for the first type in the list, and Tail for the rest of the +// list. + +// The empty type list. +struct Types0 {}; + +// Type lists of length 1, 2, 3, and so on. + +template +struct Types1 { + typedef T1 Head; + typedef Types0 Tail; +}; +template +struct Types2 { + typedef T1 Head; + typedef Types1 Tail; +}; + +template +struct Types3 { + typedef T1 Head; + typedef Types2 Tail; +}; + +template +struct Types4 { + typedef T1 Head; + typedef Types3 Tail; +}; + +template +struct Types5 { + typedef T1 Head; + typedef Types4 Tail; +}; + +template +struct Types6 { + typedef T1 Head; + typedef Types5 Tail; +}; + +template +struct Types7 { + typedef T1 Head; + typedef Types6 Tail; +}; + +template +struct Types8 { + typedef T1 Head; + typedef Types7 Tail; +}; + +template +struct Types9 { + typedef T1 Head; + typedef Types8 Tail; +}; + +template +struct Types10 { + typedef T1 Head; + typedef Types9 Tail; +}; + +template +struct Types11 { + typedef T1 Head; + typedef Types10 Tail; +}; + +template +struct Types12 { + typedef T1 Head; + typedef Types11 Tail; +}; + +template +struct Types13 { + typedef T1 Head; + typedef Types12 Tail; +}; + +template +struct Types14 { + typedef T1 Head; + typedef Types13 Tail; +}; + +template +struct Types15 { + typedef T1 Head; + typedef Types14 Tail; +}; + +template +struct Types16 { + typedef T1 Head; + typedef Types15 Tail; +}; + +template +struct Types17 { + typedef T1 Head; + typedef Types16 Tail; +}; + +template +struct Types18 { + typedef T1 Head; + typedef Types17 Tail; +}; + +template +struct Types19 { + typedef T1 Head; + typedef Types18 Tail; +}; + +template +struct Types20 { + typedef T1 Head; + typedef Types19 Tail; +}; + +template +struct Types21 { + typedef T1 Head; + typedef Types20 Tail; +}; + +template +struct Types22 { + typedef T1 Head; + typedef Types21 Tail; +}; + +template +struct Types23 { + typedef T1 Head; + typedef Types22 Tail; +}; + +template +struct Types24 { + typedef T1 Head; + typedef Types23 Tail; +}; + +template +struct Types25 { + typedef T1 Head; + typedef Types24 Tail; +}; + +template +struct Types26 { + typedef T1 Head; + typedef Types25 Tail; +}; + +template +struct Types27 { + typedef T1 Head; + typedef Types26 Tail; +}; + +template +struct Types28 { + typedef T1 Head; + typedef Types27 Tail; +}; + +template +struct Types29 { + typedef T1 Head; + typedef Types28 Tail; +}; + +template +struct Types30 { + typedef T1 Head; + typedef Types29 Tail; +}; + +template +struct Types31 { + typedef T1 Head; + typedef Types30 Tail; +}; + +template +struct Types32 { + typedef T1 Head; + typedef Types31 Tail; +}; + +template +struct Types33 { + typedef T1 Head; + typedef Types32 Tail; +}; + +template +struct Types34 { + typedef T1 Head; + typedef Types33 Tail; +}; + +template +struct Types35 { + typedef T1 Head; + typedef Types34 Tail; +}; + +template +struct Types36 { + typedef T1 Head; + typedef Types35 Tail; +}; + +template +struct Types37 { + typedef T1 Head; + typedef Types36 Tail; +}; + +template +struct Types38 { + typedef T1 Head; + typedef Types37 Tail; +}; + +template +struct Types39 { + typedef T1 Head; + typedef Types38 Tail; +}; + +template +struct Types40 { + typedef T1 Head; + typedef Types39 Tail; +}; + +template +struct Types41 { + typedef T1 Head; + typedef Types40 Tail; +}; + +template +struct Types42 { + typedef T1 Head; + typedef Types41 Tail; +}; + +template +struct Types43 { + typedef T1 Head; + typedef Types42 Tail; +}; + +template +struct Types44 { + typedef T1 Head; + typedef Types43 Tail; +}; + +template +struct Types45 { + typedef T1 Head; + typedef Types44 Tail; +}; + +template +struct Types46 { + typedef T1 Head; + typedef Types45 Tail; +}; + +template +struct Types47 { + typedef T1 Head; + typedef Types46 Tail; +}; + +template +struct Types48 { + typedef T1 Head; + typedef Types47 Tail; +}; + +template +struct Types49 { + typedef T1 Head; + typedef Types48 Tail; +}; + +template +struct Types50 { + typedef T1 Head; + typedef Types49 Tail; +}; + + +} // namespace internal + +// We don't want to require the users to write TypesN<...> directly, +// as that would require them to count the length. Types<...> is much +// easier to write, but generates horrible messages when there is a +// compiler error, as gcc insists on printing out each template +// argument, even if it has the default value (this means Types +// will appear as Types in the compiler +// errors). +// +// Our solution is to combine the best part of the two approaches: a +// user would write Types, and Google Test will translate +// that to TypesN internally to make error messages +// readable. The translation is done by the 'type' member of the +// Types template. +template +struct Types { + typedef internal::Types50 type; +}; + +template <> +struct Types { + typedef internal::Types0 type; +}; +template +struct Types { + typedef internal::Types1 type; +}; +template +struct Types { + typedef internal::Types2 type; +}; +template +struct Types { + typedef internal::Types3 type; +}; +template +struct Types { + typedef internal::Types4 type; +}; +template +struct Types { + typedef internal::Types5 type; +}; +template +struct Types { + typedef internal::Types6 type; +}; +template +struct Types { + typedef internal::Types7 type; +}; +template +struct Types { + typedef internal::Types8 type; +}; +template +struct Types { + typedef internal::Types9 type; +}; +template +struct Types { + typedef internal::Types10 type; +}; +template +struct Types { + typedef internal::Types11 type; +}; +template +struct Types { + typedef internal::Types12 type; +}; +template +struct Types { + typedef internal::Types13 type; +}; +template +struct Types { + typedef internal::Types14 type; +}; +template +struct Types { + typedef internal::Types15 type; +}; +template +struct Types { + typedef internal::Types16 type; +}; +template +struct Types { + typedef internal::Types17 type; +}; +template +struct Types { + typedef internal::Types18 type; +}; +template +struct Types { + typedef internal::Types19 type; +}; +template +struct Types { + typedef internal::Types20 type; +}; +template +struct Types { + typedef internal::Types21 type; +}; +template +struct Types { + typedef internal::Types22 type; +}; +template +struct Types { + typedef internal::Types23 type; +}; +template +struct Types { + typedef internal::Types24 type; +}; +template +struct Types { + typedef internal::Types25 type; +}; +template +struct Types { + typedef internal::Types26 type; +}; +template +struct Types { + typedef internal::Types27 type; +}; +template +struct Types { + typedef internal::Types28 type; +}; +template +struct Types { + typedef internal::Types29 type; +}; +template +struct Types { + typedef internal::Types30 type; +}; +template +struct Types { + typedef internal::Types31 type; +}; +template +struct Types { + typedef internal::Types32 type; +}; +template +struct Types { + typedef internal::Types33 type; +}; +template +struct Types { + typedef internal::Types34 type; +}; +template +struct Types { + typedef internal::Types35 type; +}; +template +struct Types { + typedef internal::Types36 type; +}; +template +struct Types { + typedef internal::Types37 type; +}; +template +struct Types { + typedef internal::Types38 type; +}; +template +struct Types { + typedef internal::Types39 type; +}; +template +struct Types { + typedef internal::Types40 type; +}; +template +struct Types { + typedef internal::Types41 type; +}; +template +struct Types { + typedef internal::Types42 type; +}; +template +struct Types { + typedef internal::Types43 type; +}; +template +struct Types { + typedef internal::Types44 type; +}; +template +struct Types { + typedef internal::Types45 type; +}; +template +struct Types { + typedef internal::Types46 type; +}; +template +struct Types { + typedef internal::Types47 type; +}; +template +struct Types { + typedef internal::Types48 type; +}; +template +struct Types { + typedef internal::Types49 type; +}; + +namespace internal { + +# define GTEST_TEMPLATE_ template class + +// The template "selector" struct TemplateSel is used to +// represent Tmpl, which must be a class template with one type +// parameter, as a type. TemplateSel::Bind::type is defined +// as the type Tmpl. This allows us to actually instantiate the +// template "selected" by TemplateSel. +// +// This trick is necessary for simulating typedef for class templates, +// which C++ doesn't support directly. +template +struct TemplateSel { + template + struct Bind { + typedef Tmpl type; + }; +}; + +# define GTEST_BIND_(TmplSel, T) \ + TmplSel::template Bind::type + +// A unique struct template used as the default value for the +// arguments of class template Templates. This allows us to simulate +// variadic templates (e.g. Templates, Templates, +// and etc), which C++ doesn't support directly. +template +struct NoneT {}; + +// The following family of struct and struct templates are used to +// represent template lists. In particular, TemplatesN represents a list of N templates (T1, T2, ..., and TN). Except +// for Templates0, every struct in the family has two member types: +// Head for the selector of the first template in the list, and Tail +// for the rest of the list. + +// The empty template list. +struct Templates0 {}; + +// Template lists of length 1, 2, 3, and so on. + +template +struct Templates1 { + typedef TemplateSel Head; + typedef Templates0 Tail; +}; +template +struct Templates2 { + typedef TemplateSel Head; + typedef Templates1 Tail; +}; + +template +struct Templates3 { + typedef TemplateSel Head; + typedef Templates2 Tail; +}; + +template +struct Templates4 { + typedef TemplateSel Head; + typedef Templates3 Tail; +}; + +template +struct Templates5 { + typedef TemplateSel Head; + typedef Templates4 Tail; +}; + +template +struct Templates6 { + typedef TemplateSel Head; + typedef Templates5 Tail; +}; + +template +struct Templates7 { + typedef TemplateSel Head; + typedef Templates6 Tail; +}; + +template +struct Templates8 { + typedef TemplateSel Head; + typedef Templates7 Tail; +}; + +template +struct Templates9 { + typedef TemplateSel Head; + typedef Templates8 Tail; +}; + +template +struct Templates10 { + typedef TemplateSel Head; + typedef Templates9 Tail; +}; + +template +struct Templates11 { + typedef TemplateSel Head; + typedef Templates10 Tail; +}; + +template +struct Templates12 { + typedef TemplateSel Head; + typedef Templates11 Tail; +}; + +template +struct Templates13 { + typedef TemplateSel Head; + typedef Templates12 Tail; +}; + +template +struct Templates14 { + typedef TemplateSel Head; + typedef Templates13 Tail; +}; + +template +struct Templates15 { + typedef TemplateSel Head; + typedef Templates14 Tail; +}; + +template +struct Templates16 { + typedef TemplateSel Head; + typedef Templates15 Tail; +}; + +template +struct Templates17 { + typedef TemplateSel Head; + typedef Templates16 Tail; +}; + +template +struct Templates18 { + typedef TemplateSel Head; + typedef Templates17 Tail; +}; + +template +struct Templates19 { + typedef TemplateSel Head; + typedef Templates18 Tail; +}; + +template +struct Templates20 { + typedef TemplateSel Head; + typedef Templates19 Tail; +}; + +template +struct Templates21 { + typedef TemplateSel Head; + typedef Templates20 Tail; +}; + +template +struct Templates22 { + typedef TemplateSel Head; + typedef Templates21 Tail; +}; + +template +struct Templates23 { + typedef TemplateSel Head; + typedef Templates22 Tail; +}; + +template +struct Templates24 { + typedef TemplateSel Head; + typedef Templates23 Tail; +}; + +template +struct Templates25 { + typedef TemplateSel Head; + typedef Templates24 Tail; +}; + +template +struct Templates26 { + typedef TemplateSel Head; + typedef Templates25 Tail; +}; + +template +struct Templates27 { + typedef TemplateSel Head; + typedef Templates26 Tail; +}; + +template +struct Templates28 { + typedef TemplateSel Head; + typedef Templates27 Tail; +}; + +template +struct Templates29 { + typedef TemplateSel Head; + typedef Templates28 Tail; +}; + +template +struct Templates30 { + typedef TemplateSel Head; + typedef Templates29 Tail; +}; + +template +struct Templates31 { + typedef TemplateSel Head; + typedef Templates30 Tail; +}; + +template +struct Templates32 { + typedef TemplateSel Head; + typedef Templates31 Tail; +}; + +template +struct Templates33 { + typedef TemplateSel Head; + typedef Templates32 Tail; +}; + +template +struct Templates34 { + typedef TemplateSel Head; + typedef Templates33 Tail; +}; + +template +struct Templates35 { + typedef TemplateSel Head; + typedef Templates34 Tail; +}; + +template +struct Templates36 { + typedef TemplateSel Head; + typedef Templates35 Tail; +}; + +template +struct Templates37 { + typedef TemplateSel Head; + typedef Templates36 Tail; +}; + +template +struct Templates38 { + typedef TemplateSel Head; + typedef Templates37 Tail; +}; + +template +struct Templates39 { + typedef TemplateSel Head; + typedef Templates38 Tail; +}; + +template +struct Templates40 { + typedef TemplateSel Head; + typedef Templates39 Tail; +}; + +template +struct Templates41 { + typedef TemplateSel Head; + typedef Templates40 Tail; +}; + +template +struct Templates42 { + typedef TemplateSel Head; + typedef Templates41 Tail; +}; + +template +struct Templates43 { + typedef TemplateSel Head; + typedef Templates42 Tail; +}; + +template +struct Templates44 { + typedef TemplateSel Head; + typedef Templates43 Tail; +}; + +template +struct Templates45 { + typedef TemplateSel Head; + typedef Templates44 Tail; +}; + +template +struct Templates46 { + typedef TemplateSel Head; + typedef Templates45 Tail; +}; + +template +struct Templates47 { + typedef TemplateSel Head; + typedef Templates46 Tail; +}; + +template +struct Templates48 { + typedef TemplateSel Head; + typedef Templates47 Tail; +}; + +template +struct Templates49 { + typedef TemplateSel Head; + typedef Templates48 Tail; +}; + +template +struct Templates50 { + typedef TemplateSel Head; + typedef Templates49 Tail; +}; + + +// We don't want to require the users to write TemplatesN<...> directly, +// as that would require them to count the length. Templates<...> is much +// easier to write, but generates horrible messages when there is a +// compiler error, as gcc insists on printing out each template +// argument, even if it has the default value (this means Templates +// will appear as Templates in the compiler +// errors). +// +// Our solution is to combine the best part of the two approaches: a +// user would write Templates, and Google Test will translate +// that to TemplatesN internally to make error messages +// readable. The translation is done by the 'type' member of the +// Templates template. +template +struct Templates { + typedef Templates50 type; +}; + +template <> +struct Templates { + typedef Templates0 type; +}; +template +struct Templates { + typedef Templates1 type; +}; +template +struct Templates { + typedef Templates2 type; +}; +template +struct Templates { + typedef Templates3 type; +}; +template +struct Templates { + typedef Templates4 type; +}; +template +struct Templates { + typedef Templates5 type; +}; +template +struct Templates { + typedef Templates6 type; +}; +template +struct Templates { + typedef Templates7 type; +}; +template +struct Templates { + typedef Templates8 type; +}; +template +struct Templates { + typedef Templates9 type; +}; +template +struct Templates { + typedef Templates10 type; +}; +template +struct Templates { + typedef Templates11 type; +}; +template +struct Templates { + typedef Templates12 type; +}; +template +struct Templates { + typedef Templates13 type; +}; +template +struct Templates { + typedef Templates14 type; +}; +template +struct Templates { + typedef Templates15 type; +}; +template +struct Templates { + typedef Templates16 type; +}; +template +struct Templates { + typedef Templates17 type; +}; +template +struct Templates { + typedef Templates18 type; +}; +template +struct Templates { + typedef Templates19 type; +}; +template +struct Templates { + typedef Templates20 type; +}; +template +struct Templates { + typedef Templates21 type; +}; +template +struct Templates { + typedef Templates22 type; +}; +template +struct Templates { + typedef Templates23 type; +}; +template +struct Templates { + typedef Templates24 type; +}; +template +struct Templates { + typedef Templates25 type; +}; +template +struct Templates { + typedef Templates26 type; +}; +template +struct Templates { + typedef Templates27 type; +}; +template +struct Templates { + typedef Templates28 type; +}; +template +struct Templates { + typedef Templates29 type; +}; +template +struct Templates { + typedef Templates30 type; +}; +template +struct Templates { + typedef Templates31 type; +}; +template +struct Templates { + typedef Templates32 type; +}; +template +struct Templates { + typedef Templates33 type; +}; +template +struct Templates { + typedef Templates34 type; +}; +template +struct Templates { + typedef Templates35 type; +}; +template +struct Templates { + typedef Templates36 type; +}; +template +struct Templates { + typedef Templates37 type; +}; +template +struct Templates { + typedef Templates38 type; +}; +template +struct Templates { + typedef Templates39 type; +}; +template +struct Templates { + typedef Templates40 type; +}; +template +struct Templates { + typedef Templates41 type; +}; +template +struct Templates { + typedef Templates42 type; +}; +template +struct Templates { + typedef Templates43 type; +}; +template +struct Templates { + typedef Templates44 type; +}; +template +struct Templates { + typedef Templates45 type; +}; +template +struct Templates { + typedef Templates46 type; +}; +template +struct Templates { + typedef Templates47 type; +}; +template +struct Templates { + typedef Templates48 type; +}; +template +struct Templates { + typedef Templates49 type; +}; + +// The TypeList template makes it possible to use either a single type +// or a Types<...> list in TYPED_TEST_CASE() and +// INSTANTIATE_TYPED_TEST_CASE_P(). + +template +struct TypeList { + typedef Types1 type; +}; + +template +struct TypeList > { + typedef typename Types::type type; +}; + +#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ + +// Due to C++ preprocessor weirdness, we need double indirection to +// concatenate two tokens when one of them is __LINE__. Writing +// +// foo ## __LINE__ +// +// will result in the token foo__LINE__, instead of foo followed by +// the current line number. For more details, see +// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6 +#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar) +#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar + +class ProtocolMessage; +namespace proto2 { class Message; } + +namespace testing { + +// Forward declarations. + +class AssertionResult; // Result of an assertion. +class Message; // Represents a failure message. +class Test; // Represents a test. +class TestInfo; // Information about a test. +class TestPartResult; // Result of a test part. +class UnitTest; // A collection of test cases. + +template +::std::string PrintToString(const T& value); + +namespace internal { + +struct TraceInfo; // Information about a trace point. +class ScopedTrace; // Implements scoped trace. +class TestInfoImpl; // Opaque implementation of TestInfo +class UnitTestImpl; // Opaque implementation of UnitTest + +// How many times InitGoogleTest() has been called. +GTEST_API_ extern int g_init_gtest_count; + +// The text used in failure messages to indicate the start of the +// stack trace. +GTEST_API_ extern const char kStackTraceMarker[]; + +// Two overloaded helpers for checking at compile time whether an +// expression is a null pointer literal (i.e. NULL or any 0-valued +// compile-time integral constant). Their return values have +// different sizes, so we can use sizeof() to test which version is +// picked by the compiler. These helpers have no implementations, as +// we only need their signatures. +// +// Given IsNullLiteralHelper(x), the compiler will pick the first +// version if x can be implicitly converted to Secret*, and pick the +// second version otherwise. Since Secret is a secret and incomplete +// type, the only expression a user can write that has type Secret* is +// a null pointer literal. Therefore, we know that x is a null +// pointer literal if and only if the first version is picked by the +// compiler. +char IsNullLiteralHelper(Secret* p); +char (&IsNullLiteralHelper(...))[2]; // NOLINT + +// A compile-time bool constant that is true if and only if x is a +// null pointer literal (i.e. NULL or any 0-valued compile-time +// integral constant). +#ifdef GTEST_ELLIPSIS_NEEDS_POD_ +// We lose support for NULL detection where the compiler doesn't like +// passing non-POD classes through ellipsis (...). +# define GTEST_IS_NULL_LITERAL_(x) false +#else +# define GTEST_IS_NULL_LITERAL_(x) \ + (sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1) +#endif // GTEST_ELLIPSIS_NEEDS_POD_ + +// Appends the user-supplied message to the Google-Test-generated message. +GTEST_API_ std::string AppendUserMessage( + const std::string& gtest_msg, const Message& user_msg); + +#if GTEST_HAS_EXCEPTIONS + +// This exception is thrown by (and only by) a failed Google Test +// assertion when GTEST_FLAG(throw_on_failure) is true (if exceptions +// are enabled). We derive it from std::runtime_error, which is for +// errors presumably detectable only at run time. Since +// std::runtime_error inherits from std::exception, many testing +// frameworks know how to extract and print the message inside it. +class GTEST_API_ GoogleTestFailureException : public ::std::runtime_error { + public: + explicit GoogleTestFailureException(const TestPartResult& failure); +}; + +#endif // GTEST_HAS_EXCEPTIONS + +// A helper class for creating scoped traces in user programs. +class GTEST_API_ ScopedTrace { + public: + // The c'tor pushes the given source file location and message onto + // a trace stack maintained by Google Test. + ScopedTrace(const char* file, int line, const Message& message); + + // The d'tor pops the info pushed by the c'tor. + // + // Note that the d'tor is not virtual in order to be efficient. + // Don't inherit from ScopedTrace! + ~ScopedTrace(); + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace); +} GTEST_ATTRIBUTE_UNUSED_; // A ScopedTrace object does its job in its + // c'tor and d'tor. Therefore it doesn't + // need to be used otherwise. + +// Constructs and returns the message for an equality assertion +// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure. +// +// The first four parameters are the expressions used in the assertion +// and their values, as strings. For example, for ASSERT_EQ(foo, bar) +// where foo is 5 and bar is 6, we have: +// +// expected_expression: "foo" +// actual_expression: "bar" +// expected_value: "5" +// actual_value: "6" +// +// The ignoring_case parameter is true iff the assertion is a +// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will +// be inserted into the message. +GTEST_API_ AssertionResult EqFailure(const char* expected_expression, + const char* actual_expression, + const std::string& expected_value, + const std::string& actual_value, + bool ignoring_case); + +// Constructs a failure message for Boolean assertions such as EXPECT_TRUE. +GTEST_API_ std::string GetBoolAssertionFailureMessage( + const AssertionResult& assertion_result, + const char* expression_text, + const char* actual_predicate_value, + const char* expected_predicate_value); + +// This template class represents an IEEE floating-point number +// (either single-precision or double-precision, depending on the +// template parameters). +// +// The purpose of this class is to do more sophisticated number +// comparison. (Due to round-off error, etc, it's very unlikely that +// two floating-points will be equal exactly. Hence a naive +// comparison by the == operation often doesn't work.) +// +// Format of IEEE floating-point: +// +// The most-significant bit being the leftmost, an IEEE +// floating-point looks like +// +// sign_bit exponent_bits fraction_bits +// +// Here, sign_bit is a single bit that designates the sign of the +// number. +// +// For float, there are 8 exponent bits and 23 fraction bits. +// +// For double, there are 11 exponent bits and 52 fraction bits. +// +// More details can be found at +// http://en.wikipedia.org/wiki/IEEE_floating-point_standard. +// +// Template parameter: +// +// RawType: the raw floating-point type (either float or double) +template +class FloatingPoint { + public: + // Defines the unsigned integer type that has the same size as the + // floating point number. + typedef typename TypeWithSize::UInt Bits; + + // Constants. + + // # of bits in a number. + static const size_t kBitCount = 8*sizeof(RawType); + + // # of fraction bits in a number. + static const size_t kFractionBitCount = + std::numeric_limits::digits - 1; + + // # of exponent bits in a number. + static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount; + + // The mask for the sign bit. + static const Bits kSignBitMask = static_cast(1) << (kBitCount - 1); + + // The mask for the fraction bits. + static const Bits kFractionBitMask = + ~static_cast(0) >> (kExponentBitCount + 1); + + // The mask for the exponent bits. + static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask); + + // How many ULP's (Units in the Last Place) we want to tolerate when + // comparing two numbers. The larger the value, the more error we + // allow. A 0 value means that two numbers must be exactly the same + // to be considered equal. + // + // The maximum error of a single floating-point operation is 0.5 + // units in the last place. On Intel CPU's, all floating-point + // calculations are done with 80-bit precision, while double has 64 + // bits. Therefore, 4 should be enough for ordinary use. + // + // See the following article for more details on ULP: + // http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ + static const size_t kMaxUlps = 4; + + // Constructs a FloatingPoint from a raw floating-point number. + // + // On an Intel CPU, passing a non-normalized NAN (Not a Number) + // around may change its bits, although the new value is guaranteed + // to be also a NAN. Therefore, don't expect this constructor to + // preserve the bits in x when x is a NAN. + explicit FloatingPoint(const RawType& x) { u_.value_ = x; } + + // Static methods + + // Reinterprets a bit pattern as a floating-point number. + // + // This function is needed to test the AlmostEquals() method. + static RawType ReinterpretBits(const Bits bits) { + FloatingPoint fp(0); + fp.u_.bits_ = bits; + return fp.u_.value_; + } + + // Returns the floating-point number that represent positive infinity. + static RawType Infinity() { + return ReinterpretBits(kExponentBitMask); + } + + // Returns the maximum representable finite floating-point number. + static RawType Max(); + + // Non-static methods + + // Returns the bits that represents this number. + const Bits &bits() const { return u_.bits_; } + + // Returns the exponent bits of this number. + Bits exponent_bits() const { return kExponentBitMask & u_.bits_; } + + // Returns the fraction bits of this number. + Bits fraction_bits() const { return kFractionBitMask & u_.bits_; } + + // Returns the sign bit of this number. + Bits sign_bit() const { return kSignBitMask & u_.bits_; } + + // Returns true iff this is NAN (not a number). + bool is_nan() const { + // It's a NAN if the exponent bits are all ones and the fraction + // bits are not entirely zeros. + return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0); + } + + // Returns true iff this number is at most kMaxUlps ULP's away from + // rhs. In particular, this function: + // + // - returns false if either number is (or both are) NAN. + // - treats really large numbers as almost equal to infinity. + // - thinks +0.0 and -0.0 are 0 DLP's apart. + bool AlmostEquals(const FloatingPoint& rhs) const { + // The IEEE standard says that any comparison operation involving + // a NAN must return false. + if (is_nan() || rhs.is_nan()) return false; + + return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_) + <= kMaxUlps; + } + + private: + // The data type used to store the actual floating-point number. + union FloatingPointUnion { + RawType value_; // The raw floating-point number. + Bits bits_; // The bits that represent the number. + }; + + // Converts an integer from the sign-and-magnitude representation to + // the biased representation. More precisely, let N be 2 to the + // power of (kBitCount - 1), an integer x is represented by the + // unsigned number x + N. + // + // For instance, + // + // -N + 1 (the most negative number representable using + // sign-and-magnitude) is represented by 1; + // 0 is represented by N; and + // N - 1 (the biggest number representable using + // sign-and-magnitude) is represented by 2N - 1. + // + // Read http://en.wikipedia.org/wiki/Signed_number_representations + // for more details on signed number representations. + static Bits SignAndMagnitudeToBiased(const Bits &sam) { + if (kSignBitMask & sam) { + // sam represents a negative number. + return ~sam + 1; + } else { + // sam represents a positive number. + return kSignBitMask | sam; + } + } + + // Given two numbers in the sign-and-magnitude representation, + // returns the distance between them as an unsigned number. + static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1, + const Bits &sam2) { + const Bits biased1 = SignAndMagnitudeToBiased(sam1); + const Bits biased2 = SignAndMagnitudeToBiased(sam2); + return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1); + } + + FloatingPointUnion u_; +}; + +// We cannot use std::numeric_limits::max() as it clashes with the max() +// macro defined by . +template <> +inline float FloatingPoint::Max() { return FLT_MAX; } +template <> +inline double FloatingPoint::Max() { return DBL_MAX; } + +// Typedefs the instances of the FloatingPoint template class that we +// care to use. +typedef FloatingPoint Float; +typedef FloatingPoint Double; + +// In order to catch the mistake of putting tests that use different +// test fixture classes in the same test case, we need to assign +// unique IDs to fixture classes and compare them. The TypeId type is +// used to hold such IDs. The user should treat TypeId as an opaque +// type: the only operation allowed on TypeId values is to compare +// them for equality using the == operator. +typedef const void* TypeId; + +template +class TypeIdHelper { + public: + // dummy_ must not have a const type. Otherwise an overly eager + // compiler (e.g. MSVC 7.1 & 8.0) may try to merge + // TypeIdHelper::dummy_ for different Ts as an "optimization". + static bool dummy_; +}; + +template +bool TypeIdHelper::dummy_ = false; + +// GetTypeId() returns the ID of type T. Different values will be +// returned for different types. Calling the function twice with the +// same type argument is guaranteed to return the same ID. +template +TypeId GetTypeId() { + // The compiler is required to allocate a different + // TypeIdHelper::dummy_ variable for each T used to instantiate + // the template. Therefore, the address of dummy_ is guaranteed to + // be unique. + return &(TypeIdHelper::dummy_); +} + +// Returns the type ID of ::testing::Test. Always call this instead +// of GetTypeId< ::testing::Test>() to get the type ID of +// ::testing::Test, as the latter may give the wrong result due to a +// suspected linker bug when compiling Google Test as a Mac OS X +// framework. +GTEST_API_ TypeId GetTestTypeId(); + +// Defines the abstract factory interface that creates instances +// of a Test object. +class TestFactoryBase { + public: + virtual ~TestFactoryBase() {} + + // Creates a test instance to run. The instance is both created and destroyed + // within TestInfoImpl::Run() + virtual Test* CreateTest() = 0; + + protected: + TestFactoryBase() {} + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestFactoryBase); +}; + +// This class provides implementation of TeastFactoryBase interface. +// It is used in TEST and TEST_F macros. +template +class TestFactoryImpl : public TestFactoryBase { + public: + virtual Test* CreateTest() { return new TestClass; } +}; + +#if GTEST_OS_WINDOWS + +// Predicate-formatters for implementing the HRESULT checking macros +// {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED} +// We pass a long instead of HRESULT to avoid causing an +// include dependency for the HRESULT type. +GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr, + long hr); // NOLINT +GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr, + long hr); // NOLINT + +#endif // GTEST_OS_WINDOWS + +// Types of SetUpTestCase() and TearDownTestCase() functions. +typedef void (*SetUpTestCaseFunc)(); +typedef void (*TearDownTestCaseFunc)(); + +// Creates a new TestInfo object and registers it with Google Test; +// returns the created object. +// +// Arguments: +// +// test_case_name: name of the test case +// name: name of the test +// type_param the name of the test's type parameter, or NULL if +// this is not a typed or a type-parameterized test. +// value_param text representation of the test's value parameter, +// or NULL if this is not a type-parameterized test. +// fixture_class_id: ID of the test fixture class +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +// factory: pointer to the factory that creates a test object. +// The newly created TestInfo instance will assume +// ownership of the factory object. +GTEST_API_ TestInfo* MakeAndRegisterTestInfo( + const char* test_case_name, + const char* name, + const char* type_param, + const char* value_param, + TypeId fixture_class_id, + SetUpTestCaseFunc set_up_tc, + TearDownTestCaseFunc tear_down_tc, + TestFactoryBase* factory); + +// If *pstr starts with the given prefix, modifies *pstr to be right +// past the prefix and returns true; otherwise leaves *pstr unchanged +// and returns false. None of pstr, *pstr, and prefix can be NULL. +GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr); + +#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +// State of the definition of a type-parameterized test case. +class GTEST_API_ TypedTestCasePState { + public: + TypedTestCasePState() : registered_(false) {} + + // Adds the given test name to defined_test_names_ and return true + // if the test case hasn't been registered; otherwise aborts the + // program. + bool AddTestName(const char* file, int line, const char* case_name, + const char* test_name) { + if (registered_) { + fprintf(stderr, "%s Test %s must be defined before " + "REGISTER_TYPED_TEST_CASE_P(%s, ...).\n", + FormatFileLocation(file, line).c_str(), test_name, case_name); + fflush(stderr); + posix::Abort(); + } + defined_test_names_.insert(test_name); + return true; + } + + // Verifies that registered_tests match the test names in + // defined_test_names_; returns registered_tests if successful, or + // aborts the program otherwise. + const char* VerifyRegisteredTestNames( + const char* file, int line, const char* registered_tests); + + private: + bool registered_; + ::std::set defined_test_names_; +}; + +// Skips to the first non-space char after the first comma in 'str'; +// returns NULL if no comma is found in 'str'. +inline const char* SkipComma(const char* str) { + const char* comma = strchr(str, ','); + if (comma == NULL) { + return NULL; + } + while (IsSpace(*(++comma))) {} + return comma; +} + +// Returns the prefix of 'str' before the first comma in it; returns +// the entire string if it contains no comma. +inline std::string GetPrefixUntilComma(const char* str) { + const char* comma = strchr(str, ','); + return comma == NULL ? str : std::string(str, comma); +} + +// TypeParameterizedTest::Register() +// registers a list of type-parameterized tests with Google Test. The +// return value is insignificant - we just need to return something +// such that we can call this function in a namespace scope. +// +// Implementation note: The GTEST_TEMPLATE_ macro declares a template +// template parameter. It's defined in gtest-type-util.h. +template +class TypeParameterizedTest { + public: + // 'index' is the index of the test in the type list 'Types' + // specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase, + // Types). Valid values for 'index' are [0, N - 1] where N is the + // length of Types. + static bool Register(const char* prefix, const char* case_name, + const char* test_names, int index) { + typedef typename Types::Head Type; + typedef Fixture FixtureClass; + typedef typename GTEST_BIND_(TestSel, Type) TestClass; + + // First, registers the first type-parameterized test in the type + // list. + MakeAndRegisterTestInfo( + (std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name + "/" + + StreamableToString(index)).c_str(), + GetPrefixUntilComma(test_names).c_str(), + GetTypeName().c_str(), + NULL, // No value parameter. + GetTypeId(), + TestClass::SetUpTestCase, + TestClass::TearDownTestCase, + new TestFactoryImpl); + + // Next, recurses (at compile time) with the tail of the type list. + return TypeParameterizedTest + ::Register(prefix, case_name, test_names, index + 1); + } +}; + +// The base case for the compile time recursion. +template +class TypeParameterizedTest { + public: + static bool Register(const char* /*prefix*/, const char* /*case_name*/, + const char* /*test_names*/, int /*index*/) { + return true; + } +}; + +// TypeParameterizedTestCase::Register() +// registers *all combinations* of 'Tests' and 'Types' with Google +// Test. The return value is insignificant - we just need to return +// something such that we can call this function in a namespace scope. +template +class TypeParameterizedTestCase { + public: + static bool Register(const char* prefix, const char* case_name, + const char* test_names) { + typedef typename Tests::Head Head; + + // First, register the first test in 'Test' for each type in 'Types'. + TypeParameterizedTest::Register( + prefix, case_name, test_names, 0); + + // Next, recurses (at compile time) with the tail of the test list. + return TypeParameterizedTestCase + ::Register(prefix, case_name, SkipComma(test_names)); + } +}; + +// The base case for the compile time recursion. +template +class TypeParameterizedTestCase { + public: + static bool Register(const char* /*prefix*/, const char* /*case_name*/, + const char* /*test_names*/) { + return true; + } +}; + +#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +// Returns the current OS stack trace as an std::string. +// +// The maximum number of stack frames to be included is specified by +// the gtest_stack_trace_depth flag. The skip_count parameter +// specifies the number of top frames to be skipped, which doesn't +// count against the number of frames to be included. +// +// For example, if Foo() calls Bar(), which in turn calls +// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in +// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't. +GTEST_API_ std::string GetCurrentOsStackTraceExceptTop( + UnitTest* unit_test, int skip_count); + +// Helpers for suppressing warnings on unreachable code or constant +// condition. + +// Always returns true. +GTEST_API_ bool AlwaysTrue(); + +// Always returns false. +inline bool AlwaysFalse() { return !AlwaysTrue(); } + +// Helper for suppressing false warning from Clang on a const char* +// variable declared in a conditional expression always being NULL in +// the else branch. +struct GTEST_API_ ConstCharPtr { + ConstCharPtr(const char* str) : value(str) {} + operator bool() const { return true; } + const char* value; +}; + +// A simple Linear Congruential Generator for generating random +// numbers with a uniform distribution. Unlike rand() and srand(), it +// doesn't use global state (and therefore can't interfere with user +// code). Unlike rand_r(), it's portable. An LCG isn't very random, +// but it's good enough for our purposes. +class GTEST_API_ Random { + public: + static const UInt32 kMaxRange = 1u << 31; + + explicit Random(UInt32 seed) : state_(seed) {} + + void Reseed(UInt32 seed) { state_ = seed; } + + // Generates a random number from [0, range). Crashes if 'range' is + // 0 or greater than kMaxRange. + UInt32 Generate(UInt32 range); + + private: + UInt32 state_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(Random); +}; + +// Defining a variable of type CompileAssertTypesEqual will cause a +// compiler error iff T1 and T2 are different types. +template +struct CompileAssertTypesEqual; + +template +struct CompileAssertTypesEqual { +}; + +// Removes the reference from a type if it is a reference type, +// otherwise leaves it unchanged. This is the same as +// tr1::remove_reference, which is not widely available yet. +template +struct RemoveReference { typedef T type; }; // NOLINT +template +struct RemoveReference { typedef T type; }; // NOLINT + +// A handy wrapper around RemoveReference that works when the argument +// T depends on template parameters. +#define GTEST_REMOVE_REFERENCE_(T) \ + typename ::testing::internal::RemoveReference::type + +// Removes const from a type if it is a const type, otherwise leaves +// it unchanged. This is the same as tr1::remove_const, which is not +// widely available yet. +template +struct RemoveConst { typedef T type; }; // NOLINT +template +struct RemoveConst { typedef T type; }; // NOLINT + +// MSVC 8.0, Sun C++, and IBM XL C++ have a bug which causes the above +// definition to fail to remove the const in 'const int[3]' and 'const +// char[3][4]'. The following specialization works around the bug. +template +struct RemoveConst { + typedef typename RemoveConst::type type[N]; +}; + +#if defined(_MSC_VER) && _MSC_VER < 1400 +// This is the only specialization that allows VC++ 7.1 to remove const in +// 'const int[3] and 'const int[3][4]'. However, it causes trouble with GCC +// and thus needs to be conditionally compiled. +template +struct RemoveConst { + typedef typename RemoveConst::type type[N]; +}; +#endif + +// A handy wrapper around RemoveConst that works when the argument +// T depends on template parameters. +#define GTEST_REMOVE_CONST_(T) \ + typename ::testing::internal::RemoveConst::type + +// Turns const U&, U&, const U, and U all into U. +#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \ + GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T)) + +// Adds reference to a type if it is not a reference type, +// otherwise leaves it unchanged. This is the same as +// tr1::add_reference, which is not widely available yet. +template +struct AddReference { typedef T& type; }; // NOLINT +template +struct AddReference { typedef T& type; }; // NOLINT + +// A handy wrapper around AddReference that works when the argument T +// depends on template parameters. +#define GTEST_ADD_REFERENCE_(T) \ + typename ::testing::internal::AddReference::type + +// Adds a reference to const on top of T as necessary. For example, +// it transforms +// +// char ==> const char& +// const char ==> const char& +// char& ==> const char& +// const char& ==> const char& +// +// The argument T must depend on some template parameters. +#define GTEST_REFERENCE_TO_CONST_(T) \ + GTEST_ADD_REFERENCE_(const GTEST_REMOVE_REFERENCE_(T)) + +// ImplicitlyConvertible::value is a compile-time bool +// constant that's true iff type From can be implicitly converted to +// type To. +template +class ImplicitlyConvertible { + private: + // We need the following helper functions only for their types. + // They have no implementations. + + // MakeFrom() is an expression whose type is From. We cannot simply + // use From(), as the type From may not have a public default + // constructor. + static From MakeFrom(); + + // These two functions are overloaded. Given an expression + // Helper(x), the compiler will pick the first version if x can be + // implicitly converted to type To; otherwise it will pick the + // second version. + // + // The first version returns a value of size 1, and the second + // version returns a value of size 2. Therefore, by checking the + // size of Helper(x), which can be done at compile time, we can tell + // which version of Helper() is used, and hence whether x can be + // implicitly converted to type To. + static char Helper(To); + static char (&Helper(...))[2]; // NOLINT + + // We have to put the 'public' section after the 'private' section, + // or MSVC refuses to compile the code. + public: + // MSVC warns about implicitly converting from double to int for + // possible loss of data, so we need to temporarily disable the + // warning. +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4244) // Temporarily disables warning 4244. + + static const bool value = + sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1; +# pragma warning(pop) // Restores the warning state. +#elif defined(__BORLANDC__) + // C++Builder cannot use member overload resolution during template + // instantiation. The simplest workaround is to use its C++0x type traits + // functions (C++Builder 2009 and above only). + static const bool value = __is_convertible(From, To); +#else + static const bool value = + sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1; +#endif // _MSV_VER +}; +template +const bool ImplicitlyConvertible::value; + +// IsAProtocolMessage::value is a compile-time bool constant that's +// true iff T is type ProtocolMessage, proto2::Message, or a subclass +// of those. +template +struct IsAProtocolMessage + : public bool_constant< + ImplicitlyConvertible::value || + ImplicitlyConvertible::value> { +}; + +// When the compiler sees expression IsContainerTest(0), if C is an +// STL-style container class, the first overload of IsContainerTest +// will be viable (since both C::iterator* and C::const_iterator* are +// valid types and NULL can be implicitly converted to them). It will +// be picked over the second overload as 'int' is a perfect match for +// the type of argument 0. If C::iterator or C::const_iterator is not +// a valid type, the first overload is not viable, and the second +// overload will be picked. Therefore, we can determine whether C is +// a container class by checking the type of IsContainerTest(0). +// The value of the expression is insignificant. +// +// Note that we look for both C::iterator and C::const_iterator. The +// reason is that C++ injects the name of a class as a member of the +// class itself (e.g. you can refer to class iterator as either +// 'iterator' or 'iterator::iterator'). If we look for C::iterator +// only, for example, we would mistakenly think that a class named +// iterator is an STL container. +// +// Also note that the simpler approach of overloading +// IsContainerTest(typename C::const_iterator*) and +// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++. +typedef int IsContainer; +template +IsContainer IsContainerTest(int /* dummy */, + typename C::iterator* /* it */ = NULL, + typename C::const_iterator* /* const_it */ = NULL) { + return 0; +} + +typedef char IsNotContainer; +template +IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; } + +// EnableIf::type is void when 'Cond' is true, and +// undefined when 'Cond' is false. To use SFINAE to make a function +// overload only apply when a particular expression is true, add +// "typename EnableIf::type* = 0" as the last parameter. +template struct EnableIf; +template<> struct EnableIf { typedef void type; }; // NOLINT + +// Utilities for native arrays. + +// ArrayEq() compares two k-dimensional native arrays using the +// elements' operator==, where k can be any integer >= 0. When k is +// 0, ArrayEq() degenerates into comparing a single pair of values. + +template +bool ArrayEq(const T* lhs, size_t size, const U* rhs); + +// This generic version is used when k is 0. +template +inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; } + +// This overload is used when k >= 1. +template +inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) { + return internal::ArrayEq(lhs, N, rhs); +} + +// This helper reduces code bloat. If we instead put its logic inside +// the previous ArrayEq() function, arrays with different sizes would +// lead to different copies of the template code. +template +bool ArrayEq(const T* lhs, size_t size, const U* rhs) { + for (size_t i = 0; i != size; i++) { + if (!internal::ArrayEq(lhs[i], rhs[i])) + return false; + } + return true; +} + +// Finds the first element in the iterator range [begin, end) that +// equals elem. Element may be a native array type itself. +template +Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) { + for (Iter it = begin; it != end; ++it) { + if (internal::ArrayEq(*it, elem)) + return it; + } + return end; +} + +// CopyArray() copies a k-dimensional native array using the elements' +// operator=, where k can be any integer >= 0. When k is 0, +// CopyArray() degenerates into copying a single value. + +template +void CopyArray(const T* from, size_t size, U* to); + +// This generic version is used when k is 0. +template +inline void CopyArray(const T& from, U* to) { *to = from; } + +// This overload is used when k >= 1. +template +inline void CopyArray(const T(&from)[N], U(*to)[N]) { + internal::CopyArray(from, N, *to); +} + +// This helper reduces code bloat. If we instead put its logic inside +// the previous CopyArray() function, arrays with different sizes +// would lead to different copies of the template code. +template +void CopyArray(const T* from, size_t size, U* to) { + for (size_t i = 0; i != size; i++) { + internal::CopyArray(from[i], to + i); + } +} + +// The relation between an NativeArray object (see below) and the +// native array it represents. +enum RelationToSource { + kReference, // The NativeArray references the native array. + kCopy // The NativeArray makes a copy of the native array and + // owns the copy. +}; + +// Adapts a native array to a read-only STL-style container. Instead +// of the complete STL container concept, this adaptor only implements +// members useful for Google Mock's container matchers. New members +// should be added as needed. To simplify the implementation, we only +// support Element being a raw type (i.e. having no top-level const or +// reference modifier). It's the client's responsibility to satisfy +// this requirement. Element can be an array type itself (hence +// multi-dimensional arrays are supported). +template +class NativeArray { + public: + // STL-style container typedefs. + typedef Element value_type; + typedef Element* iterator; + typedef const Element* const_iterator; + + // Constructs from a native array. + NativeArray(const Element* array, size_t count, RelationToSource relation) { + Init(array, count, relation); + } + + // Copy constructor. + NativeArray(const NativeArray& rhs) { + Init(rhs.array_, rhs.size_, rhs.relation_to_source_); + } + + ~NativeArray() { + // Ensures that the user doesn't instantiate NativeArray with a + // const or reference type. + static_cast(StaticAssertTypeEqHelper()); + if (relation_to_source_ == kCopy) + delete[] array_; + } + + // STL-style container methods. + size_t size() const { return size_; } + const_iterator begin() const { return array_; } + const_iterator end() const { return array_ + size_; } + bool operator==(const NativeArray& rhs) const { + return size() == rhs.size() && + ArrayEq(begin(), size(), rhs.begin()); + } + + private: + // Initializes this object; makes a copy of the input array if + // 'relation' is kCopy. + void Init(const Element* array, size_t a_size, RelationToSource relation) { + if (relation == kReference) { + array_ = array; + } else { + Element* const copy = new Element[a_size]; + CopyArray(array, a_size, copy); + array_ = copy; + } + size_ = a_size; + relation_to_source_ = relation; + } + + const Element* array_; + size_t size_; + RelationToSource relation_to_source_; + + GTEST_DISALLOW_ASSIGN_(NativeArray); +}; + +} // namespace internal +} // namespace testing + +#define GTEST_MESSAGE_AT_(file, line, message, result_type) \ + ::testing::internal::AssertHelper(result_type, file, line, message) \ + = ::testing::Message() + +#define GTEST_MESSAGE_(message, result_type) \ + GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type) + +#define GTEST_FATAL_FAILURE_(message) \ + return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure) + +#define GTEST_NONFATAL_FAILURE_(message) \ + GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure) + +#define GTEST_SUCCESS_(message) \ + GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess) + +// Suppresses MSVC warnings 4072 (unreachable code) for the code following +// statement if it returns or throws (or doesn't return or throw in some +// situations). +#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \ + if (::testing::internal::AlwaysTrue()) { statement; } + +#define GTEST_TEST_THROW_(statement, expected_exception, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::ConstCharPtr gtest_msg = "") { \ + bool gtest_caught_expected = false; \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } \ + catch (expected_exception const&) { \ + gtest_caught_expected = true; \ + } \ + catch (...) { \ + gtest_msg.value = \ + "Expected: " #statement " throws an exception of type " \ + #expected_exception ".\n Actual: it throws a different type."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ + } \ + if (!gtest_caught_expected) { \ + gtest_msg.value = \ + "Expected: " #statement " throws an exception of type " \ + #expected_exception ".\n Actual: it throws nothing."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \ + fail(gtest_msg.value) + +#define GTEST_TEST_NO_THROW_(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } \ + catch (...) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \ + fail("Expected: " #statement " doesn't throw an exception.\n" \ + " Actual: it throws.") + +#define GTEST_TEST_ANY_THROW_(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + bool gtest_caught_any = false; \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } \ + catch (...) { \ + gtest_caught_any = true; \ + } \ + if (!gtest_caught_any) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \ + fail("Expected: " #statement " throws an exception.\n" \ + " Actual: it doesn't.") + + +// Implements Boolean test assertions such as EXPECT_TRUE. expression can be +// either a boolean expression or an AssertionResult. text is a textual +// represenation of expression as it was passed into the EXPECT_TRUE. +#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (const ::testing::AssertionResult gtest_ar_ = \ + ::testing::AssertionResult(expression)) \ + ; \ + else \ + fail(::testing::internal::GetBoolAssertionFailureMessage(\ + gtest_ar_, text, #actual, #expected).c_str()) + +#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + ::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \ + fail("Expected: " #statement " doesn't generate new fatal " \ + "failures in the current thread.\n" \ + " Actual: it does.") + +// Expands to the name of the class that implements the given test. +#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ + test_case_name##_##test_name##_Test + +// Helper macro for defining tests. +#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\ +class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\ + public:\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\ + private:\ + virtual void TestBody();\ + static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\ + GTEST_DISALLOW_COPY_AND_ASSIGN_(\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\ +};\ +\ +::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\ + ::test_info_ =\ + ::testing::internal::MakeAndRegisterTestInfo(\ + #test_case_name, #test_name, NULL, NULL, \ + (parent_id), \ + parent_class::SetUpTestCase, \ + parent_class::TearDownTestCase, \ + new ::testing::internal::TestFactoryImpl<\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\ +void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ +// 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 +// 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) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines the public API for death tests. It is +// #included by gtest.h so a user doesn't need to include this +// directly. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ + +// 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 +// 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. +// +// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines internal utilities needed for implementing +// death tests. They are subject to change without notice. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ + + +#include + +namespace testing { +namespace internal { + +GTEST_DECLARE_string_(internal_run_death_test); + +// Names of the flags (needed for parsing Google Test flags). +const char kDeathTestStyleFlag[] = "death_test_style"; +const char kDeathTestUseFork[] = "death_test_use_fork"; +const char kInternalRunDeathTestFlag[] = "internal_run_death_test"; + +#if GTEST_HAS_DEATH_TEST + +// DeathTest is a class that hides much of the complexity of the +// GTEST_DEATH_TEST_ macro. It is abstract; its static Create method +// returns a concrete class that depends on the prevailing death test +// style, as defined by the --gtest_death_test_style and/or +// --gtest_internal_run_death_test flags. + +// In describing the results of death tests, these terms are used with +// the corresponding definitions: +// +// exit status: The integer exit information in the format specified +// by wait(2) +// exit code: The integer code passed to exit(3), _exit(2), or +// returned from main() +class GTEST_API_ DeathTest { + public: + // Create returns false if there was an error determining the + // appropriate action to take for the current death test; for example, + // if the gtest_death_test_style flag is set to an invalid value. + // The LastMessage method will return a more detailed message in that + // case. Otherwise, the DeathTest pointer pointed to by the "test" + // argument is set. If the death test should be skipped, the pointer + // is set to NULL; otherwise, it is set to the address of a new concrete + // DeathTest object that controls the execution of the current test. + static bool Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test); + DeathTest(); + virtual ~DeathTest() { } + + // A helper class that aborts a death test when it's deleted. + class ReturnSentinel { + public: + explicit ReturnSentinel(DeathTest* test) : test_(test) { } + ~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); } + private: + DeathTest* const test_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel); + } GTEST_ATTRIBUTE_UNUSED_; + + // An enumeration of possible roles that may be taken when a death + // test is encountered. EXECUTE means that the death test logic should + // be executed immediately. OVERSEE means that the program should prepare + // the appropriate environment for a child process to execute the death + // test, then wait for it to complete. + enum TestRole { OVERSEE_TEST, EXECUTE_TEST }; + + // An enumeration of the three reasons that a test might be aborted. + enum AbortReason { + TEST_ENCOUNTERED_RETURN_STATEMENT, + TEST_THREW_EXCEPTION, + TEST_DID_NOT_DIE + }; + + // Assumes one of the above roles. + virtual TestRole AssumeRole() = 0; + + // Waits for the death test to finish and returns its status. + virtual int Wait() = 0; + + // Returns true if the death test passed; that is, the test process + // exited during the test, its exit status matches a user-supplied + // predicate, and its stderr output matches a user-supplied regular + // expression. + // The user-supplied predicate may be a macro expression rather + // than a function pointer or functor, or else Wait and Passed could + // be combined. + virtual bool Passed(bool exit_status_ok) = 0; + + // Signals that the death test did not die as expected. + virtual void Abort(AbortReason reason) = 0; + + // Returns a human-readable outcome message regarding the outcome of + // the last death test. + static const char* LastMessage(); + + static void set_last_death_test_message(const std::string& message); + + private: + // A string containing a description of the outcome of the last death test. + static std::string last_death_test_message_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest); +}; + +// Factory interface for death tests. May be mocked out for testing. +class DeathTestFactory { + public: + virtual ~DeathTestFactory() { } + virtual bool Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test) = 0; +}; + +// A concrete DeathTestFactory implementation for normal use. +class DefaultDeathTestFactory : public DeathTestFactory { + public: + virtual bool Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test); +}; + +// Returns true if exit_status describes a process that was terminated +// by a signal, or exited normally with a nonzero exit code. +GTEST_API_ bool ExitedUnsuccessfully(int exit_status); + +// Traps C++ exceptions escaping statement and reports them as test +// failures. Note that trapping SEH exceptions is not implemented here. +# if GTEST_HAS_EXCEPTIONS +# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } catch (const ::std::exception& gtest_exception) { \ + fprintf(\ + stderr, \ + "\n%s: Caught std::exception-derived exception escaping the " \ + "death test statement. Exception message: %s\n", \ + ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \ + gtest_exception.what()); \ + fflush(stderr); \ + death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \ + } catch (...) { \ + death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \ + } + +# else +# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) + +# endif + +// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*, +// ASSERT_EXIT*, and EXPECT_EXIT*. +# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + const ::testing::internal::RE& gtest_regex = (regex); \ + ::testing::internal::DeathTest* gtest_dt; \ + if (!::testing::internal::DeathTest::Create(#statement, >est_regex, \ + __FILE__, __LINE__, >est_dt)) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ + } \ + if (gtest_dt != NULL) { \ + ::testing::internal::scoped_ptr< ::testing::internal::DeathTest> \ + gtest_dt_ptr(gtest_dt); \ + switch (gtest_dt->AssumeRole()) { \ + case ::testing::internal::DeathTest::OVERSEE_TEST: \ + if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ + } \ + break; \ + case ::testing::internal::DeathTest::EXECUTE_TEST: { \ + ::testing::internal::DeathTest::ReturnSentinel \ + gtest_sentinel(gtest_dt); \ + GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \ + gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \ + break; \ + } \ + default: \ + break; \ + } \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__): \ + fail(::testing::internal::DeathTest::LastMessage()) +// The symbol "fail" here expands to something into which a message +// can be streamed. + +// This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in +// NDEBUG mode. In this case we need the statements to be executed, the regex is +// ignored, and the macro must accept a streamed message even though the message +// is never printed. +# define GTEST_EXECUTE_STATEMENT_(statement, regex) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } else \ + ::testing::Message() + +// A class representing the parsed contents of the +// --gtest_internal_run_death_test flag, as it existed when +// RUN_ALL_TESTS was called. +class InternalRunDeathTestFlag { + public: + InternalRunDeathTestFlag(const std::string& a_file, + int a_line, + int an_index, + int a_write_fd) + : file_(a_file), line_(a_line), index_(an_index), + write_fd_(a_write_fd) {} + + ~InternalRunDeathTestFlag() { + if (write_fd_ >= 0) + posix::Close(write_fd_); + } + + const std::string& file() const { return file_; } + int line() const { return line_; } + int index() const { return index_; } + int write_fd() const { return write_fd_; } + + private: + std::string file_; + int line_; + int index_; + int write_fd_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag); +}; + +// Returns a newly created InternalRunDeathTestFlag object with fields +// initialized from the GTEST_FLAG(internal_run_death_test) flag if +// the flag is specified; otherwise returns NULL. +InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag(); + +#else // GTEST_HAS_DEATH_TEST + +// This macro is used for implementing macros such as +// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where +// death tests are not supported. Those macros must compile on such systems +// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on +// systems that support death tests. This allows one to write such a macro +// on a system that does not support death tests and be sure that it will +// compile on a death-test supporting system. +// +// Parameters: +// statement - A statement that a macro such as EXPECT_DEATH would test +// for program termination. This macro has to make sure this +// statement is compiled but not executed, to ensure that +// EXPECT_DEATH_IF_SUPPORTED compiles with a certain +// parameter iff EXPECT_DEATH compiles with it. +// regex - A regex that a macro such as EXPECT_DEATH would use to test +// the output of statement. This parameter has to be +// compiled but not evaluated by this macro, to ensure that +// this macro only accepts expressions that a macro such as +// EXPECT_DEATH would accept. +// terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED +// and a return statement for ASSERT_DEATH_IF_SUPPORTED. +// This ensures that ASSERT_DEATH_IF_SUPPORTED will not +// compile inside functions where ASSERT_DEATH doesn't +// compile. +// +// The branch that has an always false condition is used to ensure that +// statement and regex are compiled (and thus syntactically correct) but +// never executed. The unreachable code macro protects the terminator +// statement from generating an 'unreachable code' warning in case +// statement unconditionally returns or throws. The Message constructor at +// the end allows the syntax of streaming additional messages into the +// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH. +# define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + GTEST_LOG_(WARNING) \ + << "Death tests are not supported on this platform.\n" \ + << "Statement '" #statement "' cannot be verified."; \ + } else if (::testing::internal::AlwaysFalse()) { \ + ::testing::internal::RE::PartialMatch(".*", (regex)); \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + terminator; \ + } else \ + ::testing::Message() + +#endif // GTEST_HAS_DEATH_TEST + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ + +namespace testing { + +// This flag controls the style of death tests. Valid values are "threadsafe", +// meaning that the death test child process will re-execute the test binary +// from the start, running only a single death test, or "fast", +// meaning that the child process will execute the test logic immediately +// after forking. +GTEST_DECLARE_string_(death_test_style); + +#if GTEST_HAS_DEATH_TEST + +namespace internal { + +// Returns a Boolean value indicating whether the caller is currently +// executing in the context of the death test child process. Tools such as +// Valgrind heap checkers may need this to modify their behavior in death +// tests. IMPORTANT: This is an internal utility. Using it may break the +// implementation of death tests. User code MUST NOT use it. +GTEST_API_ bool InDeathTestChild(); + +} // namespace internal + +// The following macros are useful for writing death tests. + +// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is +// executed: +// +// 1. It generates a warning if there is more than one active +// thread. This is because it's safe to fork() or clone() only +// when there is a single thread. +// +// 2. The parent process clone()s a sub-process and runs the death +// test in it; the sub-process exits with code 0 at the end of the +// death test, if it hasn't exited already. +// +// 3. The parent process waits for the sub-process to terminate. +// +// 4. The parent process checks the exit code and error message of +// the sub-process. +// +// Examples: +// +// ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number"); +// for (int i = 0; i < 5; i++) { +// EXPECT_DEATH(server.ProcessRequest(i), +// "Invalid request .* in ProcessRequest()") +// << "Failed to die on request " << i; +// } +// +// ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting"); +// +// bool KilledBySIGHUP(int exit_code) { +// return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP; +// } +// +// ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!"); +// +// On the regular expressions used in death tests: +// +// On POSIX-compliant systems (*nix), we use the library, +// which uses the POSIX extended regex syntax. +// +// On other platforms (e.g. Windows), we only support a simple regex +// syntax implemented as part of Google Test. This limited +// implementation should be enough most of the time when writing +// death tests; though it lacks many features you can find in PCRE +// or POSIX extended regex syntax. For example, we don't support +// union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and +// repetition count ("x{5,7}"), among others. +// +// Below is the syntax that we do support. We chose it to be a +// subset of both PCRE and POSIX extended regex, so it's easy to +// learn wherever you come from. In the following: 'A' denotes a +// literal character, period (.), or a single \\ escape sequence; +// 'x' and 'y' denote regular expressions; 'm' and 'n' are for +// natural numbers. +// +// c matches any literal character c +// \\d matches any decimal digit +// \\D matches any character that's not a decimal digit +// \\f matches \f +// \\n matches \n +// \\r matches \r +// \\s matches any ASCII whitespace, including \n +// \\S matches any character that's not a whitespace +// \\t matches \t +// \\v matches \v +// \\w matches any letter, _, or decimal digit +// \\W matches any character that \\w doesn't match +// \\c matches any literal character c, which must be a punctuation +// . matches any single character except \n +// A? matches 0 or 1 occurrences of A +// A* matches 0 or many occurrences of A +// A+ matches 1 or many occurrences of A +// ^ matches the beginning of a string (not that of each line) +// $ matches the end of a string (not that of each line) +// xy matches x followed by y +// +// If you accidentally use PCRE or POSIX extended regex features +// not implemented by us, you will get a run-time failure. In that +// case, please try to rewrite your regular expression within the +// above syntax. +// +// This implementation is *not* meant to be as highly tuned or robust +// as a compiled regex library, but should perform well enough for a +// death test, which already incurs significant overhead by launching +// a child process. +// +// Known caveats: +// +// A "threadsafe" style death test obtains the path to the test +// program from argv[0] and re-executes it in the sub-process. For +// simplicity, the current implementation doesn't search the PATH +// when launching the sub-process. This means that the user must +// invoke the test program via a path that contains at least one +// path separator (e.g. path/to/foo_test and +// /absolute/path/to/bar_test are fine, but foo_test is not). This +// is rarely a problem as people usually don't put the test binary +// directory in PATH. +// +// TODO(wan@google.com): make thread-safe death tests search the PATH. + +// Asserts that a given statement causes the program to exit, with an +// integer exit status that satisfies predicate, and emitting error output +// that matches regex. +# define ASSERT_EXIT(statement, predicate, regex) \ + GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_) + +// Like ASSERT_EXIT, but continues on to successive tests in the +// test case, if any: +# define EXPECT_EXIT(statement, predicate, regex) \ + GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_) + +// Asserts that a given statement causes the program to exit, either by +// explicitly exiting with a nonzero exit code or being killed by a +// signal, and emitting error output that matches regex. +# define ASSERT_DEATH(statement, regex) \ + ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) + +// Like ASSERT_DEATH, but continues on to successive tests in the +// test case, if any: +# define EXPECT_DEATH(statement, regex) \ + EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) + +// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*: + +// Tests that an exit code describes a normal exit with a given exit code. +class GTEST_API_ ExitedWithCode { + public: + explicit ExitedWithCode(int exit_code); + bool operator()(int exit_status) const; + private: + // No implementation - assignment is unsupported. + void operator=(const ExitedWithCode& other); + + const int exit_code_; +}; + +# if !GTEST_OS_WINDOWS +// Tests that an exit code describes an exit due to termination by a +// given signal. +class GTEST_API_ KilledBySignal { + public: + explicit KilledBySignal(int signum); + bool operator()(int exit_status) const; + private: + const int signum_; +}; +# endif // !GTEST_OS_WINDOWS + +// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode. +// The death testing framework causes this to have interesting semantics, +// since the sideeffects of the call are only visible in opt mode, and not +// in debug mode. +// +// In practice, this can be used to test functions that utilize the +// LOG(DFATAL) macro using the following style: +// +// int DieInDebugOr12(int* sideeffect) { +// if (sideeffect) { +// *sideeffect = 12; +// } +// LOG(DFATAL) << "death"; +// return 12; +// } +// +// TEST(TestCase, TestDieOr12WorksInDgbAndOpt) { +// int sideeffect = 0; +// // Only asserts in dbg. +// EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death"); +// +// #ifdef NDEBUG +// // opt-mode has sideeffect visible. +// EXPECT_EQ(12, sideeffect); +// #else +// // dbg-mode no visible sideeffect. +// EXPECT_EQ(0, sideeffect); +// #endif +// } +// +// This will assert that DieInDebugReturn12InOpt() crashes in debug +// mode, usually due to a DCHECK or LOG(DFATAL), but returns the +// appropriate fallback value (12 in this case) in opt mode. If you +// need to test that a function has appropriate side-effects in opt +// mode, include assertions against the side-effects. A general +// pattern for this is: +// +// EXPECT_DEBUG_DEATH({ +// // Side-effects here will have an effect after this statement in +// // opt mode, but none in debug mode. +// EXPECT_EQ(12, DieInDebugOr12(&sideeffect)); +// }, "death"); +// +# ifdef NDEBUG + +# define EXPECT_DEBUG_DEATH(statement, regex) \ + GTEST_EXECUTE_STATEMENT_(statement, regex) + +# define ASSERT_DEBUG_DEATH(statement, regex) \ + GTEST_EXECUTE_STATEMENT_(statement, regex) + +# else + +# define EXPECT_DEBUG_DEATH(statement, regex) \ + EXPECT_DEATH(statement, regex) + +# define ASSERT_DEBUG_DEATH(statement, regex) \ + ASSERT_DEATH(statement, regex) + +# endif // NDEBUG for EXPECT_DEBUG_DEATH +#endif // GTEST_HAS_DEATH_TEST + +// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and +// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if +// death tests are supported; otherwise they just issue a warning. This is +// useful when you are combining death test assertions with normal test +// assertions in one test. +#if GTEST_HAS_DEATH_TEST +# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ + EXPECT_DEATH(statement, regex) +# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \ + ASSERT_DEATH(statement, regex) +#else +# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ + GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, ) +# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \ + GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return) +#endif + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ +// This file was GENERATED by command: +// pump.py gtest-param-test.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2008, 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. +// +// Authors: vladl@google.com (Vlad Losev) +// +// Macros and functions for implementing parameterized tests +// in Google C++ Testing Framework (Google Test) +// +// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! +// +#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ + + +// Value-parameterized tests allow you to test your code with different +// parameters without writing multiple copies of the same test. +// +// Here is how you use value-parameterized tests: + +#if 0 + +// To write value-parameterized tests, first you should define a fixture +// class. It is usually derived from testing::TestWithParam (see below for +// another inheritance scheme that's sometimes useful in more complicated +// class hierarchies), where the type of your parameter values. +// TestWithParam is itself derived from testing::Test. T can be any +// copyable type. If it's a raw pointer, you are responsible for managing the +// lifespan of the pointed values. + +class FooTest : public ::testing::TestWithParam { + // You can implement all the usual class fixture members here. +}; + +// Then, use the TEST_P macro to define as many parameterized tests +// for this fixture as you want. The _P suffix is for "parameterized" +// or "pattern", whichever you prefer to think. + +TEST_P(FooTest, DoesBlah) { + // Inside a test, access the test parameter with the GetParam() method + // of the TestWithParam class: + EXPECT_TRUE(foo.Blah(GetParam())); + ... +} + +TEST_P(FooTest, HasBlahBlah) { + ... +} + +// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test +// case with any set of parameters you want. Google Test defines a number +// of functions for generating test parameters. They return what we call +// (surprise!) parameter generators. Here is a summary of them, which +// are all in the testing namespace: +// +// +// Range(begin, end [, step]) - Yields values {begin, begin+step, +// begin+step+step, ...}. The values do not +// include end. step defaults to 1. +// Values(v1, v2, ..., vN) - Yields values {v1, v2, ..., vN}. +// ValuesIn(container) - Yields values from a C-style array, an STL +// ValuesIn(begin,end) container, or an iterator range [begin, end). +// Bool() - Yields sequence {false, true}. +// Combine(g1, g2, ..., gN) - Yields all combinations (the Cartesian product +// for the math savvy) of the values generated +// by the N generators. +// +// For more details, see comments at the definitions of these functions below +// in this file. +// +// The following statement will instantiate tests from the FooTest test case +// each with parameter values "meeny", "miny", and "moe". + +INSTANTIATE_TEST_CASE_P(InstantiationName, + FooTest, + Values("meeny", "miny", "moe")); + +// To distinguish different instances of the pattern, (yes, you +// can instantiate it more then once) the first argument to the +// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the +// actual test case name. Remember to pick unique prefixes for different +// instantiations. The tests from the instantiation above will have +// these names: +// +// * InstantiationName/FooTest.DoesBlah/0 for "meeny" +// * InstantiationName/FooTest.DoesBlah/1 for "miny" +// * InstantiationName/FooTest.DoesBlah/2 for "moe" +// * InstantiationName/FooTest.HasBlahBlah/0 for "meeny" +// * InstantiationName/FooTest.HasBlahBlah/1 for "miny" +// * InstantiationName/FooTest.HasBlahBlah/2 for "moe" +// +// You can use these names in --gtest_filter. +// +// This statement will instantiate all tests from FooTest again, each +// with parameter values "cat" and "dog": + +const char* pets[] = {"cat", "dog"}; +INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets)); + +// The tests from the instantiation above will have these names: +// +// * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat" +// * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog" +// * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat" +// * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog" +// +// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests +// in the given test case, whether their definitions come before or +// AFTER the INSTANTIATE_TEST_CASE_P statement. +// +// Please also note that generator expressions (including parameters to the +// generators) are evaluated in InitGoogleTest(), after main() has started. +// This allows the user on one hand, to adjust generator parameters in order +// to dynamically determine a set of tests to run and on the other hand, +// give the user a chance to inspect the generated tests with Google Test +// reflection API before RUN_ALL_TESTS() is executed. +// +// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc +// for more examples. +// +// In the future, we plan to publish the API for defining new parameter +// generators. But for now this interface remains part of the internal +// implementation and is subject to change. +// +// +// A parameterized test fixture must be derived from testing::Test and from +// testing::WithParamInterface, where T is the type of the parameter +// values. Inheriting from TestWithParam satisfies that requirement because +// TestWithParam inherits from both Test and WithParamInterface. In more +// complicated hierarchies, however, it is occasionally useful to inherit +// separately from Test and WithParamInterface. For example: + +class BaseTest : public ::testing::Test { + // You can inherit all the usual members for a non-parameterized test + // fixture here. +}; + +class DerivedTest : public BaseTest, public ::testing::WithParamInterface { + // The usual test fixture members go here too. +}; + +TEST_F(BaseTest, HasFoo) { + // This is an ordinary non-parameterized test. +} + +TEST_P(DerivedTest, DoesBlah) { + // GetParam works just the same here as if you inherit from TestWithParam. + EXPECT_TRUE(foo.Blah(GetParam())); +} + +#endif // 0 + + +#if !GTEST_OS_SYMBIAN +# include +#endif + +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. +// Copyright 2008 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: vladl@google.com (Vlad Losev) + +// Type and function utilities for implementing parameterized tests. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ + +#include +#include +#include + +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. +// Copyright 2003 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. +// +// Authors: Dan Egnor (egnor@google.com) +// +// A "smart" pointer type with reference tracking. Every pointer to a +// particular object is kept on a circular linked list. When the last pointer +// to an object is destroyed or reassigned, the object is deleted. +// +// Used properly, this deletes the object when the last reference goes away. +// There are several caveats: +// - Like all reference counting schemes, cycles lead to leaks. +// - Each smart pointer is actually two pointers (8 bytes instead of 4). +// - Every time a pointer is assigned, the entire list of pointers to that +// object is traversed. This class is therefore NOT SUITABLE when there +// will often be more than two or three pointers to a particular object. +// - References are only tracked as long as linked_ptr<> objects are copied. +// If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS +// will happen (double deletion). +// +// A good use of this class is storing object references in STL containers. +// You can safely put linked_ptr<> in a vector<>. +// Other uses may not be as good. +// +// Note: If you use an incomplete type with linked_ptr<>, the class +// *containing* linked_ptr<> must have a constructor and destructor (even +// if they do nothing!). +// +// Bill Gibbons suggested we use something like this. +// +// Thread Safety: +// Unlike other linked_ptr implementations, in this implementation +// a linked_ptr object is thread-safe in the sense that: +// - it's safe to copy linked_ptr objects concurrently, +// - it's safe to copy *from* a linked_ptr and read its underlying +// raw pointer (e.g. via get()) concurrently, and +// - it's safe to write to two linked_ptrs that point to the same +// shared object concurrently. +// TODO(wan@google.com): rename this to safe_linked_ptr to avoid +// confusion with normal linked_ptr. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ + +#include +#include + + +namespace testing { +namespace internal { + +// Protects copying of all linked_ptr objects. +GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex); + +// This is used internally by all instances of linked_ptr<>. It needs to be +// a non-template class because different types of linked_ptr<> can refer to +// the same object (linked_ptr(obj) vs linked_ptr(obj)). +// So, it needs to be possible for different types of linked_ptr to participate +// in the same circular linked list, so we need a single class type here. +// +// DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr. +class linked_ptr_internal { + public: + // Create a new circle that includes only this instance. + void join_new() { + next_ = this; + } + + // Many linked_ptr operations may change p.link_ for some linked_ptr + // variable p in the same circle as this object. Therefore we need + // to prevent two such operations from occurring concurrently. + // + // Note that different types of linked_ptr objects can coexist in a + // circle (e.g. linked_ptr, linked_ptr, and + // linked_ptr). Therefore we must use a single mutex to + // protect all linked_ptr objects. This can create serious + // contention in production code, but is acceptable in a testing + // framework. + + // Join an existing circle. + void join(linked_ptr_internal const* ptr) + GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { + MutexLock lock(&g_linked_ptr_mutex); + + linked_ptr_internal const* p = ptr; + while (p->next_ != ptr) p = p->next_; + p->next_ = this; + next_ = ptr; + } + + // Leave whatever circle we're part of. Returns true if we were the + // last member of the circle. Once this is done, you can join() another. + bool depart() + GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { + MutexLock lock(&g_linked_ptr_mutex); + + if (next_ == this) return true; + linked_ptr_internal const* p = next_; + while (p->next_ != this) p = p->next_; + p->next_ = next_; + return false; + } + + private: + mutable linked_ptr_internal const* next_; +}; + +template +class linked_ptr { + public: + typedef T element_type; + + // Take over ownership of a raw pointer. This should happen as soon as + // possible after the object is created. + explicit linked_ptr(T* ptr = NULL) { capture(ptr); } + ~linked_ptr() { depart(); } + + // Copy an existing linked_ptr<>, adding ourselves to the list of references. + template linked_ptr(linked_ptr const& ptr) { copy(&ptr); } + linked_ptr(linked_ptr const& ptr) { // NOLINT + assert(&ptr != this); + copy(&ptr); + } + + // Assignment releases the old value and acquires the new. + template linked_ptr& operator=(linked_ptr const& ptr) { + depart(); + copy(&ptr); + return *this; + } + + linked_ptr& operator=(linked_ptr const& ptr) { + if (&ptr != this) { + depart(); + copy(&ptr); + } + return *this; + } + + // Smart pointer members. + void reset(T* ptr = NULL) { + depart(); + capture(ptr); + } + T* get() const { return value_; } + T* operator->() const { return value_; } + T& operator*() const { return *value_; } + + bool operator==(T* p) const { return value_ == p; } + bool operator!=(T* p) const { return value_ != p; } + template + bool operator==(linked_ptr const& ptr) const { + return value_ == ptr.get(); + } + template + bool operator!=(linked_ptr const& ptr) const { + return value_ != ptr.get(); + } + + private: + template + friend class linked_ptr; + + T* value_; + linked_ptr_internal link_; + + void depart() { + if (link_.depart()) delete value_; + } + + void capture(T* ptr) { + value_ = ptr; + link_.join_new(); + } + + template void copy(linked_ptr const* ptr) { + value_ = ptr->get(); + if (value_) + link_.join(&ptr->link_); + else + link_.join_new(); + } +}; + +template inline +bool operator==(T* ptr, const linked_ptr& x) { + return ptr == x.get(); +} + +template inline +bool operator!=(T* ptr, const linked_ptr& x) { + return ptr != x.get(); +} + +// A function to convert T* into linked_ptr +// Doing e.g. make_linked_ptr(new FooBarBaz(arg)) is a shorter notation +// for linked_ptr >(new FooBarBaz(arg)) +template +linked_ptr make_linked_ptr(T* ptr) { + return linked_ptr(ptr); +} + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +// Google Test - The Google C++ Testing Framework +// +// This file implements a universal value printer that can print a +// value of any type T: +// +// void ::testing::internal::UniversalPrinter::Print(value, ostream_ptr); +// +// A user can teach this function how to print a class type T by +// defining either operator<<() or PrintTo() in the namespace that +// defines T. More specifically, the FIRST defined function in the +// following list will be used (assuming T is defined in namespace +// foo): +// +// 1. foo::PrintTo(const T&, ostream*) +// 2. operator<<(ostream&, const T&) defined in either foo or the +// global namespace. +// +// If none of the above is defined, it will print the debug string of +// the value if it is a protocol buffer, or print the raw bytes in the +// value otherwise. +// +// To aid debugging: when T is a reference type, the address of the +// value is also printed; when T is a (const) char pointer, both the +// pointer value and the NUL-terminated string it points to are +// printed. +// +// We also provide some convenient wrappers: +// +// // Prints a value to a string. For a (const or not) char +// // pointer, the NUL-terminated string (but not the pointer) is +// // printed. +// std::string ::testing::PrintToString(const T& value); +// +// // Prints a value tersely: for a reference type, the referenced +// // value (but not the address) is printed; for a (const or not) char +// // pointer, the NUL-terminated string (but not the pointer) is +// // printed. +// void ::testing::internal::UniversalTersePrint(const T& value, ostream*); +// +// // Prints value using the type inferred by the compiler. The difference +// // from UniversalTersePrint() is that this function prints both the +// // pointer and the NUL-terminated string for a (const or not) char pointer. +// void ::testing::internal::UniversalPrint(const T& value, ostream*); +// +// // Prints the fields of a tuple tersely to a string vector, one +// // element for each field. Tuple support must be enabled in +// // gtest-port.h. +// std::vector UniversalTersePrintTupleFieldsToStrings( +// const Tuple& value); +// +// Known limitation: +// +// The print primitives print the elements of an STL-style container +// using the compiler-inferred type of *iter where iter is a +// const_iterator of the container. When const_iterator is an input +// iterator but not a forward iterator, this inferred type may not +// match value_type, and the print output may be incorrect. In +// practice, this is rarely a problem as for most containers +// const_iterator is a forward iterator. We'll fix this if there's an +// actual need for it. Note that this fix cannot rely on value_type +// being defined as many user-defined container types don't have +// value_type. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ + +#include // NOLINT +#include +#include +#include +#include + +namespace testing { + +// Definitions in the 'internal' and 'internal2' name spaces are +// subject to change without notice. DO NOT USE THEM IN USER CODE! +namespace internal2 { + +// Prints the given number of bytes in the given object to the given +// ostream. +GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes, + size_t count, + ::std::ostream* os); + +// For selecting which printer to use when a given type has neither << +// nor PrintTo(). +enum TypeKind { + kProtobuf, // a protobuf type + kConvertibleToInteger, // a type implicitly convertible to BiggestInt + // (e.g. a named or unnamed enum type) + kOtherType // anything else +}; + +// TypeWithoutFormatter::PrintValue(value, os) is called +// by the universal printer to print a value of type T when neither +// operator<< nor PrintTo() is defined for T, where kTypeKind is the +// "kind" of T as defined by enum TypeKind. +template +class TypeWithoutFormatter { + public: + // This default version is called when kTypeKind is kOtherType. + static void PrintValue(const T& value, ::std::ostream* os) { + PrintBytesInObjectTo(reinterpret_cast(&value), + sizeof(value), os); + } +}; + +// We print a protobuf using its ShortDebugString() when the string +// doesn't exceed this many characters; otherwise we print it using +// DebugString() for better readability. +const size_t kProtobufOneLinerMaxLength = 50; + +template +class TypeWithoutFormatter { + public: + static void PrintValue(const T& value, ::std::ostream* os) { + const ::testing::internal::string short_str = value.ShortDebugString(); + const ::testing::internal::string pretty_str = + short_str.length() <= kProtobufOneLinerMaxLength ? + short_str : ("\n" + value.DebugString()); + *os << ("<" + pretty_str + ">"); + } +}; + +template +class TypeWithoutFormatter { + public: + // Since T has no << operator or PrintTo() but can be implicitly + // converted to BiggestInt, we print it as a BiggestInt. + // + // Most likely T is an enum type (either named or unnamed), in which + // case printing it as an integer is the desired behavior. In case + // T is not an enum, printing it as an integer is the best we can do + // given that it has no user-defined printer. + static void PrintValue(const T& value, ::std::ostream* os) { + const internal::BiggestInt kBigInt = value; + *os << kBigInt; + } +}; + +// Prints the given value to the given ostream. If the value is a +// protocol message, its debug string is printed; if it's an enum or +// of a type implicitly convertible to BiggestInt, it's printed as an +// integer; otherwise the bytes in the value are printed. This is +// what UniversalPrinter::Print() does when it knows nothing about +// type T and T has neither << operator nor PrintTo(). +// +// A user can override this behavior for a class type Foo by defining +// a << operator in the namespace where Foo is defined. +// +// We put this operator in namespace 'internal2' instead of 'internal' +// to simplify the implementation, as much code in 'internal' needs to +// use << in STL, which would conflict with our own << were it defined +// in 'internal'. +// +// Note that this operator<< takes a generic std::basic_ostream type instead of the more restricted std::ostream. If +// we define it to take an std::ostream instead, we'll get an +// "ambiguous overloads" compiler error when trying to print a type +// Foo that supports streaming to std::basic_ostream, as the compiler cannot tell whether +// operator<<(std::ostream&, const T&) or +// operator<<(std::basic_stream, const Foo&) is more +// specific. +template +::std::basic_ostream& operator<<( + ::std::basic_ostream& os, const T& x) { + TypeWithoutFormatter::value ? kProtobuf : + internal::ImplicitlyConvertible::value ? + kConvertibleToInteger : kOtherType)>::PrintValue(x, &os); + return os; +} + +} // namespace internal2 +} // namespace testing + +// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up +// magic needed for implementing UniversalPrinter won't work. +namespace testing_internal { + +// Used to print a value that is not an STL-style container when the +// user doesn't define PrintTo() for it. +template +void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) { + // With the following statement, during unqualified name lookup, + // testing::internal2::operator<< appears as if it was declared in + // the nearest enclosing namespace that contains both + // ::testing_internal and ::testing::internal2, i.e. the global + // namespace. For more details, refer to the C++ Standard section + // 7.3.4-1 [namespace.udir]. This allows us to fall back onto + // testing::internal2::operator<< in case T doesn't come with a << + // operator. + // + // We cannot write 'using ::testing::internal2::operator<<;', which + // gcc 3.3 fails to compile due to a compiler bug. + using namespace ::testing::internal2; // NOLINT + + // Assuming T is defined in namespace foo, in the next statement, + // the compiler will consider all of: + // + // 1. foo::operator<< (thanks to Koenig look-up), + // 2. ::operator<< (as the current namespace is enclosed in ::), + // 3. testing::internal2::operator<< (thanks to the using statement above). + // + // The operator<< whose type matches T best will be picked. + // + // We deliberately allow #2 to be a candidate, as sometimes it's + // impossible to define #1 (e.g. when foo is ::std, defining + // anything in it is undefined behavior unless you are a compiler + // vendor.). + *os << value; +} + +} // namespace testing_internal + +namespace testing { +namespace internal { + +// UniversalPrinter::Print(value, ostream_ptr) prints the given +// value to the given ostream. The caller must ensure that +// 'ostream_ptr' is not NULL, or the behavior is undefined. +// +// We define UniversalPrinter as a class template (as opposed to a +// function template), as we need to partially specialize it for +// reference types, which cannot be done with function templates. +template +class UniversalPrinter; + +template +void UniversalPrint(const T& value, ::std::ostream* os); + +// Used to print an STL-style container when the user doesn't define +// a PrintTo() for it. +template +void DefaultPrintTo(IsContainer /* dummy */, + false_type /* is not a pointer */, + const C& container, ::std::ostream* os) { + const size_t kMaxCount = 32; // The maximum number of elements to print. + *os << '{'; + size_t count = 0; + for (typename C::const_iterator it = container.begin(); + it != container.end(); ++it, ++count) { + if (count > 0) { + *os << ','; + if (count == kMaxCount) { // Enough has been printed. + *os << " ..."; + break; + } + } + *os << ' '; + // We cannot call PrintTo(*it, os) here as PrintTo() doesn't + // handle *it being a native array. + internal::UniversalPrint(*it, os); + } + + if (count > 0) { + *os << ' '; + } + *os << '}'; +} + +// Used to print a pointer that is neither a char pointer nor a member +// pointer, when the user doesn't define PrintTo() for it. (A member +// variable pointer or member function pointer doesn't really point to +// a location in the address space. Their representation is +// implementation-defined. Therefore they will be printed as raw +// bytes.) +template +void DefaultPrintTo(IsNotContainer /* dummy */, + true_type /* is a pointer */, + T* p, ::std::ostream* os) { + if (p == NULL) { + *os << "NULL"; + } else { + // C++ doesn't allow casting from a function pointer to any object + // pointer. + // + // IsTrue() silences warnings: "Condition is always true", + // "unreachable code". + if (IsTrue(ImplicitlyConvertible::value)) { + // T is not a function type. We just call << to print p, + // relying on ADL to pick up user-defined << for their pointer + // types, if any. + *os << p; + } else { + // T is a function type, so '*os << p' doesn't do what we want + // (it just prints p as bool). We want to print p as a const + // void*. However, we cannot cast it to const void* directly, + // even using reinterpret_cast, as earlier versions of gcc + // (e.g. 3.4.5) cannot compile the cast when p is a function + // pointer. Casting to UInt64 first solves the problem. + *os << reinterpret_cast( + reinterpret_cast(p)); + } + } +} + +// Used to print a non-container, non-pointer value when the user +// doesn't define PrintTo() for it. +template +void DefaultPrintTo(IsNotContainer /* dummy */, + false_type /* is not a pointer */, + const T& value, ::std::ostream* os) { + ::testing_internal::DefaultPrintNonContainerTo(value, os); +} + +// Prints the given value using the << operator if it has one; +// otherwise prints the bytes in it. This is what +// UniversalPrinter::Print() does when PrintTo() is not specialized +// or overloaded for type T. +// +// A user can override this behavior for a class type Foo by defining +// an overload of PrintTo() in the namespace where Foo is defined. We +// give the user this option as sometimes defining a << operator for +// Foo is not desirable (e.g. the coding style may prevent doing it, +// or there is already a << operator but it doesn't do what the user +// wants). +template +void PrintTo(const T& value, ::std::ostream* os) { + // DefaultPrintTo() is overloaded. The type of its first two + // arguments determine which version will be picked. If T is an + // STL-style container, the version for container will be called; if + // T is a pointer, the pointer version will be called; otherwise the + // generic version will be called. + // + // Note that we check for container types here, prior to we check + // for protocol message types in our operator<<. The rationale is: + // + // For protocol messages, we want to give people a chance to + // override Google Mock's format by defining a PrintTo() or + // operator<<. For STL containers, other formats can be + // incompatible with Google Mock's format for the container + // elements; therefore we check for container types here to ensure + // that our format is used. + // + // The second argument of DefaultPrintTo() is needed to bypass a bug + // in Symbian's C++ compiler that prevents it from picking the right + // overload between: + // + // PrintTo(const T& x, ...); + // PrintTo(T* x, ...); + DefaultPrintTo(IsContainerTest(0), is_pointer(), value, os); +} + +// The following list of PrintTo() overloads tells +// UniversalPrinter::Print() how to print standard types (built-in +// types, strings, plain arrays, and pointers). + +// Overloads for various char types. +GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os); +GTEST_API_ void PrintTo(signed char c, ::std::ostream* os); +inline void PrintTo(char c, ::std::ostream* os) { + // When printing a plain char, we always treat it as unsigned. This + // way, the output won't be affected by whether the compiler thinks + // char is signed or not. + PrintTo(static_cast(c), os); +} + +// Overloads for other simple built-in types. +inline void PrintTo(bool x, ::std::ostream* os) { + *os << (x ? "true" : "false"); +} + +// Overload for wchar_t type. +// Prints a wchar_t as a symbol if it is printable or as its internal +// code otherwise and also as its decimal code (except for L'\0'). +// The L'\0' char is printed as "L'\\0'". The decimal code is printed +// as signed integer when wchar_t is implemented by the compiler +// as a signed type and is printed as an unsigned integer when wchar_t +// is implemented as an unsigned type. +GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os); + +// Overloads for C strings. +GTEST_API_ void PrintTo(const char* s, ::std::ostream* os); +inline void PrintTo(char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} + +// signed/unsigned char is often used for representing binary data, so +// we print pointers to it as void* to be safe. +inline void PrintTo(const signed char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +inline void PrintTo(signed char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +inline void PrintTo(const unsigned char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +inline void PrintTo(unsigned char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} + +// MSVC can be configured to define wchar_t as a typedef of unsigned +// short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native +// type. When wchar_t is a typedef, defining an overload for const +// wchar_t* would cause unsigned short* be printed as a wide string, +// possibly causing invalid memory accesses. +#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) +// Overloads for wide C strings +GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os); +inline void PrintTo(wchar_t* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +#endif + +// Overload for C arrays. Multi-dimensional arrays are printed +// properly. + +// Prints the given number of elements in an array, without printing +// the curly braces. +template +void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) { + UniversalPrint(a[0], os); + for (size_t i = 1; i != count; i++) { + *os << ", "; + UniversalPrint(a[i], os); + } +} + +// Overloads for ::string and ::std::string. +#if GTEST_HAS_GLOBAL_STRING +GTEST_API_ void PrintStringTo(const ::string&s, ::std::ostream* os); +inline void PrintTo(const ::string& s, ::std::ostream* os) { + PrintStringTo(s, os); +} +#endif // GTEST_HAS_GLOBAL_STRING + +GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os); +inline void PrintTo(const ::std::string& s, ::std::ostream* os) { + PrintStringTo(s, os); +} + +// Overloads for ::wstring and ::std::wstring. +#if GTEST_HAS_GLOBAL_WSTRING +GTEST_API_ void PrintWideStringTo(const ::wstring&s, ::std::ostream* os); +inline void PrintTo(const ::wstring& s, ::std::ostream* os) { + PrintWideStringTo(s, os); +} +#endif // GTEST_HAS_GLOBAL_WSTRING + +#if GTEST_HAS_STD_WSTRING +GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os); +inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) { + PrintWideStringTo(s, os); +} +#endif // GTEST_HAS_STD_WSTRING + +#if GTEST_HAS_TR1_TUPLE +// Overload for ::std::tr1::tuple. Needed for printing function arguments, +// which are packed as tuples. + +// Helper function for printing a tuple. T must be instantiated with +// a tuple type. +template +void PrintTupleTo(const T& t, ::std::ostream* os); + +// Overloaded PrintTo() for tuples of various arities. We support +// tuples of up-to 10 fields. The following implementation works +// regardless of whether tr1::tuple is implemented using the +// non-standard variadic template feature or not. + +inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo( + const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} +#endif // GTEST_HAS_TR1_TUPLE + +// Overload for std::pair. +template +void PrintTo(const ::std::pair& value, ::std::ostream* os) { + *os << '('; + // We cannot use UniversalPrint(value.first, os) here, as T1 may be + // a reference type. The same for printing value.second. + UniversalPrinter::Print(value.first, os); + *os << ", "; + UniversalPrinter::Print(value.second, os); + *os << ')'; +} + +// Implements printing a non-reference type T by letting the compiler +// pick the right overload of PrintTo() for T. +template +class UniversalPrinter { + public: + // MSVC warns about adding const to a function type, so we want to + // disable the warning. +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4180) // Temporarily disables warning 4180. +#endif // _MSC_VER + + // Note: we deliberately don't call this PrintTo(), as that name + // conflicts with ::testing::internal::PrintTo in the body of the + // function. + static void Print(const T& value, ::std::ostream* os) { + // By default, ::testing::internal::PrintTo() is used for printing + // the value. + // + // Thanks to Koenig look-up, if T is a class and has its own + // PrintTo() function defined in its namespace, that function will + // be visible here. Since it is more specific than the generic ones + // in ::testing::internal, it will be picked by the compiler in the + // following statement - exactly what we want. + PrintTo(value, os); + } + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif // _MSC_VER +}; + +// UniversalPrintArray(begin, len, os) prints an array of 'len' +// elements, starting at address 'begin'. +template +void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) { + if (len == 0) { + *os << "{}"; + } else { + *os << "{ "; + const size_t kThreshold = 18; + const size_t kChunkSize = 8; + // If the array has more than kThreshold elements, we'll have to + // omit some details by printing only the first and the last + // kChunkSize elements. + // TODO(wan@google.com): let the user control the threshold using a flag. + if (len <= kThreshold) { + PrintRawArrayTo(begin, len, os); + } else { + PrintRawArrayTo(begin, kChunkSize, os); + *os << ", ..., "; + PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os); + } + *os << " }"; + } +} +// This overload prints a (const) char array compactly. +GTEST_API_ void UniversalPrintArray( + const char* begin, size_t len, ::std::ostream* os); + +// This overload prints a (const) wchar_t array compactly. +GTEST_API_ void UniversalPrintArray( + const wchar_t* begin, size_t len, ::std::ostream* os); + +// Implements printing an array type T[N]. +template +class UniversalPrinter { + public: + // Prints the given array, omitting some elements when there are too + // many. + static void Print(const T (&a)[N], ::std::ostream* os) { + UniversalPrintArray(a, N, os); + } +}; + +// Implements printing a reference type T&. +template +class UniversalPrinter { + public: + // MSVC warns about adding const to a function type, so we want to + // disable the warning. +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4180) // Temporarily disables warning 4180. +#endif // _MSC_VER + + static void Print(const T& value, ::std::ostream* os) { + // Prints the address of the value. We use reinterpret_cast here + // as static_cast doesn't compile when T is a function type. + *os << "@" << reinterpret_cast(&value) << " "; + + // Then prints the value itself. + UniversalPrint(value, os); + } + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif // _MSC_VER +}; + +// Prints a value tersely: for a reference type, the referenced value +// (but not the address) is printed; for a (const) char pointer, the +// NUL-terminated string (but not the pointer) is printed. + +template +class UniversalTersePrinter { + public: + static void Print(const T& value, ::std::ostream* os) { + UniversalPrint(value, os); + } +}; +template +class UniversalTersePrinter { + public: + static void Print(const T& value, ::std::ostream* os) { + UniversalPrint(value, os); + } +}; +template +class UniversalTersePrinter { + public: + static void Print(const T (&value)[N], ::std::ostream* os) { + UniversalPrinter::Print(value, os); + } +}; +template <> +class UniversalTersePrinter { + public: + static void Print(const char* str, ::std::ostream* os) { + if (str == NULL) { + *os << "NULL"; + } else { + UniversalPrint(string(str), os); + } + } +}; +template <> +class UniversalTersePrinter { + public: + static void Print(char* str, ::std::ostream* os) { + UniversalTersePrinter::Print(str, os); + } +}; + +#if GTEST_HAS_STD_WSTRING +template <> +class UniversalTersePrinter { + public: + static void Print(const wchar_t* str, ::std::ostream* os) { + if (str == NULL) { + *os << "NULL"; + } else { + UniversalPrint(::std::wstring(str), os); + } + } +}; +#endif + +template <> +class UniversalTersePrinter { + public: + static void Print(wchar_t* str, ::std::ostream* os) { + UniversalTersePrinter::Print(str, os); + } +}; + +template +void UniversalTersePrint(const T& value, ::std::ostream* os) { + UniversalTersePrinter::Print(value, os); +} + +// Prints a value using the type inferred by the compiler. The +// difference between this and UniversalTersePrint() is that for a +// (const) char pointer, this prints both the pointer and the +// NUL-terminated string. +template +void UniversalPrint(const T& value, ::std::ostream* os) { + // A workarond for the bug in VC++ 7.1 that prevents us from instantiating + // UniversalPrinter with T directly. + typedef T T1; + UniversalPrinter::Print(value, os); +} + +#if GTEST_HAS_TR1_TUPLE +typedef ::std::vector Strings; + +// This helper template allows PrintTo() for tuples and +// UniversalTersePrintTupleFieldsToStrings() to be defined by +// induction on the number of tuple fields. The idea is that +// TuplePrefixPrinter::PrintPrefixTo(t, os) prints the first N +// fields in tuple t, and can be defined in terms of +// TuplePrefixPrinter. + +// The inductive case. +template +struct TuplePrefixPrinter { + // Prints the first N fields of a tuple. + template + static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) { + TuplePrefixPrinter::PrintPrefixTo(t, os); + *os << ", "; + UniversalPrinter::type> + ::Print(::std::tr1::get(t), os); + } + + // Tersely prints the first N fields of a tuple to a string vector, + // one element for each field. + template + static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) { + TuplePrefixPrinter::TersePrintPrefixToStrings(t, strings); + ::std::stringstream ss; + UniversalTersePrint(::std::tr1::get(t), &ss); + strings->push_back(ss.str()); + } +}; + +// Base cases. +template <> +struct TuplePrefixPrinter<0> { + template + static void PrintPrefixTo(const Tuple&, ::std::ostream*) {} + + template + static void TersePrintPrefixToStrings(const Tuple&, Strings*) {} +}; +// We have to specialize the entire TuplePrefixPrinter<> class +// template here, even though the definition of +// TersePrintPrefixToStrings() is the same as the generic version, as +// Embarcadero (formerly CodeGear, formerly Borland) C++ doesn't +// support specializing a method template of a class template. +template <> +struct TuplePrefixPrinter<1> { + template + static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) { + UniversalPrinter::type>:: + Print(::std::tr1::get<0>(t), os); + } + + template + static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) { + ::std::stringstream ss; + UniversalTersePrint(::std::tr1::get<0>(t), &ss); + strings->push_back(ss.str()); + } +}; + +// Helper function for printing a tuple. T must be instantiated with +// a tuple type. +template +void PrintTupleTo(const T& t, ::std::ostream* os) { + *os << "("; + TuplePrefixPrinter< ::std::tr1::tuple_size::value>:: + PrintPrefixTo(t, os); + *os << ")"; +} + +// Prints the fields of a tuple tersely to a string vector, one +// element for each field. See the comment before +// UniversalTersePrint() for how we define "tersely". +template +Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) { + Strings result; + TuplePrefixPrinter< ::std::tr1::tuple_size::value>:: + TersePrintPrefixToStrings(value, &result); + return result; +} +#endif // GTEST_HAS_TR1_TUPLE + +} // namespace internal + +template +::std::string PrintToString(const T& value) { + ::std::stringstream ss; + internal::UniversalTersePrinter::Print(value, &ss); + return ss.str(); +} + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ + +#if GTEST_HAS_PARAM_TEST + +namespace testing { +namespace internal { + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Outputs a message explaining invalid registration of different +// fixture class for the same test case. This may happen when +// TEST_P macro is used to define two tests with the same name +// but in different namespaces. +GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name, + const char* file, int line); + +template class ParamGeneratorInterface; +template class ParamGenerator; + +// Interface for iterating over elements provided by an implementation +// of ParamGeneratorInterface. +template +class ParamIteratorInterface { + public: + virtual ~ParamIteratorInterface() {} + // A pointer to the base generator instance. + // Used only for the purposes of iterator comparison + // to make sure that two iterators belong to the same generator. + virtual const ParamGeneratorInterface* BaseGenerator() const = 0; + // Advances iterator to point to the next element + // provided by the generator. The caller is responsible + // for not calling Advance() on an iterator equal to + // BaseGenerator()->End(). + virtual void Advance() = 0; + // Clones the iterator object. Used for implementing copy semantics + // of ParamIterator. + virtual ParamIteratorInterface* Clone() const = 0; + // Dereferences the current iterator and provides (read-only) access + // to the pointed value. It is the caller's responsibility not to call + // Current() on an iterator equal to BaseGenerator()->End(). + // Used for implementing ParamGenerator::operator*(). + virtual const T* Current() const = 0; + // Determines whether the given iterator and other point to the same + // element in the sequence generated by the generator. + // Used for implementing ParamGenerator::operator==(). + virtual bool Equals(const ParamIteratorInterface& other) const = 0; +}; + +// Class iterating over elements provided by an implementation of +// ParamGeneratorInterface. It wraps ParamIteratorInterface +// and implements the const forward iterator concept. +template +class ParamIterator { + public: + typedef T value_type; + typedef const T& reference; + typedef ptrdiff_t difference_type; + + // ParamIterator assumes ownership of the impl_ pointer. + ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {} + ParamIterator& operator=(const ParamIterator& other) { + if (this != &other) + impl_.reset(other.impl_->Clone()); + return *this; + } + + const T& operator*() const { return *impl_->Current(); } + const T* operator->() const { return impl_->Current(); } + // Prefix version of operator++. + ParamIterator& operator++() { + impl_->Advance(); + return *this; + } + // Postfix version of operator++. + ParamIterator operator++(int /*unused*/) { + ParamIteratorInterface* clone = impl_->Clone(); + impl_->Advance(); + return ParamIterator(clone); + } + bool operator==(const ParamIterator& other) const { + return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_); + } + bool operator!=(const ParamIterator& other) const { + return !(*this == other); + } + + private: + friend class ParamGenerator; + explicit ParamIterator(ParamIteratorInterface* impl) : impl_(impl) {} + scoped_ptr > impl_; +}; + +// ParamGeneratorInterface is the binary interface to access generators +// defined in other translation units. +template +class ParamGeneratorInterface { + public: + typedef T ParamType; + + virtual ~ParamGeneratorInterface() {} + + // Generator interface definition + virtual ParamIteratorInterface* Begin() const = 0; + virtual ParamIteratorInterface* End() const = 0; +}; + +// Wraps ParamGeneratorInterface and provides general generator syntax +// compatible with the STL Container concept. +// This class implements copy initialization semantics and the contained +// ParamGeneratorInterface instance is shared among all copies +// of the original object. This is possible because that instance is immutable. +template +class ParamGenerator { + public: + typedef ParamIterator iterator; + + explicit ParamGenerator(ParamGeneratorInterface* impl) : impl_(impl) {} + ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {} + + ParamGenerator& operator=(const ParamGenerator& other) { + impl_ = other.impl_; + return *this; + } + + iterator begin() const { return iterator(impl_->Begin()); } + iterator end() const { return iterator(impl_->End()); } + + private: + linked_ptr > impl_; +}; + +// Generates values from a range of two comparable values. Can be used to +// generate sequences of user-defined types that implement operator+() and +// operator<(). +// This class is used in the Range() function. +template +class RangeGenerator : public ParamGeneratorInterface { + public: + RangeGenerator(T begin, T end, IncrementT step) + : begin_(begin), end_(end), + step_(step), end_index_(CalculateEndIndex(begin, end, step)) {} + virtual ~RangeGenerator() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, begin_, 0, step_); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, end_, end_index_, step_); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, T value, int index, + IncrementT step) + : base_(base), value_(value), index_(index), step_(step) {} + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + virtual void Advance() { + value_ = value_ + step_; + index_++; + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const T* Current() const { return &value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const int other_index = + CheckedDowncastToActualType(&other)->index_; + return index_ == other_index; + } + + private: + Iterator(const Iterator& other) + : ParamIteratorInterface(), + base_(other.base_), value_(other.value_), index_(other.index_), + step_(other.step_) {} + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + T value_; + int index_; + const IncrementT step_; + }; // class RangeGenerator::Iterator + + static int CalculateEndIndex(const T& begin, + const T& end, + const IncrementT& step) { + int end_index = 0; + for (T i = begin; i < end; i = i + step) + end_index++; + return end_index; + } + + // No implementation - assignment is unsupported. + void operator=(const RangeGenerator& other); + + const T begin_; + const T end_; + const IncrementT step_; + // The index for the end() iterator. All the elements in the generated + // sequence are indexed (0-based) to aid iterator comparison. + const int end_index_; +}; // class RangeGenerator + + +// Generates values from a pair of STL-style iterators. Used in the +// ValuesIn() function. The elements are copied from the source range +// since the source can be located on the stack, and the generator +// is likely to persist beyond that stack frame. +template +class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface { + public: + template + ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end) + : container_(begin, end) {} + virtual ~ValuesInIteratorRangeGenerator() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, container_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, container_.end()); + } + + private: + typedef typename ::std::vector ContainerType; + + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + typename ContainerType::const_iterator iterator) + : base_(base), iterator_(iterator) {} + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + virtual void Advance() { + ++iterator_; + value_.reset(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + // We need to use cached value referenced by iterator_ because *iterator_ + // can return a temporary object (and of type other then T), so just + // having "return &*iterator_;" doesn't work. + // value_ is updated here and not in Advance() because Advance() + // can advance iterator_ beyond the end of the range, and we cannot + // detect that fact. The client code, on the other hand, is + // responsible for not calling Current() on an out-of-range iterator. + virtual const T* Current() const { + if (value_.get() == NULL) + value_.reset(new T(*iterator_)); + return value_.get(); + } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + return iterator_ == + CheckedDowncastToActualType(&other)->iterator_; + } + + private: + Iterator(const Iterator& other) + // The explicit constructor call suppresses a false warning + // emitted by gcc when supplied with the -Wextra option. + : ParamIteratorInterface(), + base_(other.base_), + iterator_(other.iterator_) {} + + const ParamGeneratorInterface* const base_; + typename ContainerType::const_iterator iterator_; + // A cached value of *iterator_. We keep it here to allow access by + // pointer in the wrapping iterator's operator->(). + // value_ needs to be mutable to be accessed in Current(). + // Use of scoped_ptr helps manage cached value's lifetime, + // which is bound by the lifespan of the iterator itself. + mutable scoped_ptr value_; + }; // class ValuesInIteratorRangeGenerator::Iterator + + // No implementation - assignment is unsupported. + void operator=(const ValuesInIteratorRangeGenerator& other); + + const ContainerType container_; +}; // class ValuesInIteratorRangeGenerator + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Stores a parameter value and later creates tests parameterized with that +// value. +template +class ParameterizedTestFactory : public TestFactoryBase { + public: + typedef typename TestClass::ParamType ParamType; + explicit ParameterizedTestFactory(ParamType parameter) : + parameter_(parameter) {} + virtual Test* CreateTest() { + TestClass::SetParam(¶meter_); + return new TestClass(); + } + + private: + const ParamType parameter_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory); +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// TestMetaFactoryBase is a base class for meta-factories that create +// test factories for passing into MakeAndRegisterTestInfo function. +template +class TestMetaFactoryBase { + public: + virtual ~TestMetaFactoryBase() {} + + virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0; +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// TestMetaFactory creates test factories for passing into +// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives +// ownership of test factory pointer, same factory object cannot be passed +// into that method twice. But ParameterizedTestCaseInfo is going to call +// it for each Test/Parameter value combination. Thus it needs meta factory +// creator class. +template +class TestMetaFactory + : public TestMetaFactoryBase { + public: + typedef typename TestCase::ParamType ParamType; + + TestMetaFactory() {} + + virtual TestFactoryBase* CreateTestFactory(ParamType parameter) { + return new ParameterizedTestFactory(parameter); + } + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory); +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// ParameterizedTestCaseInfoBase is a generic interface +// to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase +// accumulates test information provided by TEST_P macro invocations +// and generators provided by INSTANTIATE_TEST_CASE_P macro invocations +// and uses that information to register all resulting test instances +// in RegisterTests method. The ParameterizeTestCaseRegistry class holds +// a collection of pointers to the ParameterizedTestCaseInfo objects +// and calls RegisterTests() on each of them when asked. +class ParameterizedTestCaseInfoBase { + public: + virtual ~ParameterizedTestCaseInfoBase() {} + + // Base part of test case name for display purposes. + virtual const string& GetTestCaseName() const = 0; + // Test case id to verify identity. + virtual TypeId GetTestCaseTypeId() const = 0; + // UnitTest class invokes this method to register tests in this + // test case right before running them in RUN_ALL_TESTS macro. + // This method should not be called more then once on any single + // instance of a ParameterizedTestCaseInfoBase derived class. + virtual void RegisterTests() = 0; + + protected: + ParameterizedTestCaseInfoBase() {} + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase); +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// ParameterizedTestCaseInfo accumulates tests obtained from TEST_P +// macro invocations for a particular test case and generators +// obtained from INSTANTIATE_TEST_CASE_P macro invocations for that +// test case. It registers tests with all values generated by all +// generators when asked. +template +class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { + public: + // ParamType and GeneratorCreationFunc are private types but are required + // for declarations of public methods AddTestPattern() and + // AddTestCaseInstantiation(). + typedef typename TestCase::ParamType ParamType; + // A function that returns an instance of appropriate generator type. + typedef ParamGenerator(GeneratorCreationFunc)(); + + explicit ParameterizedTestCaseInfo(const char* name) + : test_case_name_(name) {} + + // Test case base name for display purposes. + virtual const string& GetTestCaseName() const { return test_case_name_; } + // Test case id to verify identity. + virtual TypeId GetTestCaseTypeId() const { return GetTypeId(); } + // TEST_P macro uses AddTestPattern() to record information + // about a single test in a LocalTestInfo structure. + // test_case_name is the base name of the test case (without invocation + // prefix). test_base_name is the name of an individual test without + // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is + // test case base name and DoBar is test base name. + void AddTestPattern(const char* test_case_name, + const char* test_base_name, + TestMetaFactoryBase* meta_factory) { + tests_.push_back(linked_ptr(new TestInfo(test_case_name, + test_base_name, + meta_factory))); + } + // INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information + // about a generator. + int AddTestCaseInstantiation(const string& instantiation_name, + GeneratorCreationFunc* func, + const char* /* file */, + int /* line */) { + instantiations_.push_back(::std::make_pair(instantiation_name, func)); + return 0; // Return value used only to run this method in namespace scope. + } + // UnitTest class invokes this method to register tests in this test case + // test cases right before running tests in RUN_ALL_TESTS macro. + // This method should not be called more then once on any single + // instance of a ParameterizedTestCaseInfoBase derived class. + // UnitTest has a guard to prevent from calling this method more then once. + virtual void RegisterTests() { + for (typename TestInfoContainer::iterator test_it = tests_.begin(); + test_it != tests_.end(); ++test_it) { + linked_ptr test_info = *test_it; + for (typename InstantiationContainer::iterator gen_it = + instantiations_.begin(); gen_it != instantiations_.end(); + ++gen_it) { + const string& instantiation_name = gen_it->first; + ParamGenerator generator((*gen_it->second)()); + + string test_case_name; + if ( !instantiation_name.empty() ) + test_case_name = instantiation_name + "/"; + test_case_name += test_info->test_case_base_name; + + int i = 0; + for (typename ParamGenerator::iterator param_it = + generator.begin(); + param_it != generator.end(); ++param_it, ++i) { + Message test_name_stream; + test_name_stream << test_info->test_base_name << "/" << i; + MakeAndRegisterTestInfo( + test_case_name.c_str(), + test_name_stream.GetString().c_str(), + NULL, // No type parameter. + PrintToString(*param_it).c_str(), + GetTestCaseTypeId(), + TestCase::SetUpTestCase, + TestCase::TearDownTestCase, + test_info->test_meta_factory->CreateTestFactory(*param_it)); + } // for param_it + } // for gen_it + } // for test_it + } // RegisterTests + + private: + // LocalTestInfo structure keeps information about a single test registered + // with TEST_P macro. + struct TestInfo { + TestInfo(const char* a_test_case_base_name, + const char* a_test_base_name, + TestMetaFactoryBase* a_test_meta_factory) : + test_case_base_name(a_test_case_base_name), + test_base_name(a_test_base_name), + test_meta_factory(a_test_meta_factory) {} + + const string test_case_base_name; + const string test_base_name; + const scoped_ptr > test_meta_factory; + }; + typedef ::std::vector > TestInfoContainer; + // Keeps pairs of + // received from INSTANTIATE_TEST_CASE_P macros. + typedef ::std::vector > + InstantiationContainer; + + const string test_case_name_; + TestInfoContainer tests_; + InstantiationContainer instantiations_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo); +}; // class ParameterizedTestCaseInfo + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// ParameterizedTestCaseRegistry contains a map of ParameterizedTestCaseInfoBase +// classes accessed by test case names. TEST_P and INSTANTIATE_TEST_CASE_P +// macros use it to locate their corresponding ParameterizedTestCaseInfo +// descriptors. +class ParameterizedTestCaseRegistry { + public: + ParameterizedTestCaseRegistry() {} + ~ParameterizedTestCaseRegistry() { + for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); + it != test_case_infos_.end(); ++it) { + delete *it; + } + } + + // Looks up or creates and returns a structure containing information about + // tests and instantiations of a particular test case. + template + ParameterizedTestCaseInfo* GetTestCasePatternHolder( + const char* test_case_name, + const char* file, + int line) { + ParameterizedTestCaseInfo* typed_test_info = NULL; + for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); + it != test_case_infos_.end(); ++it) { + if ((*it)->GetTestCaseName() == test_case_name) { + if ((*it)->GetTestCaseTypeId() != GetTypeId()) { + // Complain about incorrect usage of Google Test facilities + // and terminate the program since we cannot guaranty correct + // test case setup and tear-down in this case. + ReportInvalidTestCaseType(test_case_name, file, line); + posix::Abort(); + } else { + // At this point we are sure that the object we found is of the same + // type we are looking for, so we downcast it to that type + // without further checks. + typed_test_info = CheckedDowncastToActualType< + ParameterizedTestCaseInfo >(*it); + } + break; + } + } + if (typed_test_info == NULL) { + typed_test_info = new ParameterizedTestCaseInfo(test_case_name); + test_case_infos_.push_back(typed_test_info); + } + return typed_test_info; + } + void RegisterTests() { + for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); + it != test_case_infos_.end(); ++it) { + (*it)->RegisterTests(); + } + } + + private: + typedef ::std::vector TestCaseInfoContainer; + + TestCaseInfoContainer test_case_infos_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry); +}; + +} // namespace internal +} // namespace testing + +#endif // GTEST_HAS_PARAM_TEST + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ +// This file was GENERATED by command: +// pump.py gtest-param-util-generated.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2008 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: vladl@google.com (Vlad Losev) + +// Type and function utilities for implementing parameterized tests. +// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! +// +// Currently Google Test supports at most 50 arguments in Values, +// and at most 10 arguments in Combine. Please contact +// googletestframework@googlegroups.com if you need more. +// Please note that the number of arguments to Combine is limited +// by the maximum arity of the implementation of tr1::tuple which is +// currently set at 10. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ + +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. + +#if GTEST_HAS_PARAM_TEST + +namespace testing { + +// Forward declarations of ValuesIn(), which is implemented in +// include/gtest/gtest-param-test.h. +template +internal::ParamGenerator< + typename ::testing::internal::IteratorTraits::value_type> +ValuesIn(ForwardIterator begin, ForwardIterator end); + +template +internal::ParamGenerator ValuesIn(const T (&array)[N]); + +template +internal::ParamGenerator ValuesIn( + const Container& container); + +namespace internal { + +// Used in the Values() function to provide polymorphic capabilities. +template +class ValueArray1 { + public: + explicit ValueArray1(T1 v1) : v1_(v1) {} + + template + operator ParamGenerator() const { return ValuesIn(&v1_, &v1_ + 1); } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray1& other); + + const T1 v1_; +}; + +template +class ValueArray2 { + public: + ValueArray2(T1 v1, T2 v2) : v1_(v1), v2_(v2) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray2& other); + + const T1 v1_; + const T2 v2_; +}; + +template +class ValueArray3 { + public: + ValueArray3(T1 v1, T2 v2, T3 v3) : v1_(v1), v2_(v2), v3_(v3) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray3& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; +}; + +template +class ValueArray4 { + public: + ValueArray4(T1 v1, T2 v2, T3 v3, T4 v4) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray4& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; +}; + +template +class ValueArray5 { + public: + ValueArray5(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray5& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; +}; + +template +class ValueArray6 { + public: + ValueArray6(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray6& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; +}; + +template +class ValueArray7 { + public: + ValueArray7(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray7& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; +}; + +template +class ValueArray8 { + public: + ValueArray8(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray8& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; +}; + +template +class ValueArray9 { + public: + ValueArray9(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray9& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; +}; + +template +class ValueArray10 { + public: + ValueArray10(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray10& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; +}; + +template +class ValueArray11 { + public: + ValueArray11(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray11& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; +}; + +template +class ValueArray12 { + public: + ValueArray12(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray12& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; +}; + +template +class ValueArray13 { + public: + ValueArray13(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray13& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; +}; + +template +class ValueArray14 { + public: + ValueArray14(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray14& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; +}; + +template +class ValueArray15 { + public: + ValueArray15(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray15& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; +}; + +template +class ValueArray16 { + public: + ValueArray16(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray16& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; +}; + +template +class ValueArray17 { + public: + ValueArray17(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, + T17 v17) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray17& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; +}; + +template +class ValueArray18 { + public: + ValueArray18(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray18& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; +}; + +template +class ValueArray19 { + public: + ValueArray19(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray19& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; +}; + +template +class ValueArray20 { + public: + ValueArray20(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray20& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; +}; + +template +class ValueArray21 { + public: + ValueArray21(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray21& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; +}; + +template +class ValueArray22 { + public: + ValueArray22(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray22& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; +}; + +template +class ValueArray23 { + public: + ValueArray23(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray23& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; +}; + +template +class ValueArray24 { + public: + ValueArray24(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray24& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; +}; + +template +class ValueArray25 { + public: + ValueArray25(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, + T25 v25) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray25& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; +}; + +template +class ValueArray26 { + public: + ValueArray26(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray26& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; +}; + +template +class ValueArray27 { + public: + ValueArray27(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), + v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), + v26_(v26), v27_(v27) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray27& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; +}; + +template +class ValueArray28 { + public: + ValueArray28(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), + v25_(v25), v26_(v26), v27_(v27), v28_(v28) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray28& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; +}; + +template +class ValueArray29 { + public: + ValueArray29(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), + v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray29& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; +}; + +template +class ValueArray30 { + public: + ValueArray30(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray30& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; +}; + +template +class ValueArray31 { + public: + ValueArray31(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray31& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; +}; + +template +class ValueArray32 { + public: + ValueArray32(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), + v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray32& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; +}; + +template +class ValueArray33 { + public: + ValueArray33(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, + T33 v33) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray33& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; +}; + +template +class ValueArray34 { + public: + ValueArray34(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray34& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; +}; + +template +class ValueArray35 { + public: + ValueArray35(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), + v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), + v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), + v32_(v32), v33_(v33), v34_(v34), v35_(v35) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray35& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; +}; + +template +class ValueArray36 { + public: + ValueArray36(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), + v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), + v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray36& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; +}; + +template +class ValueArray37 { + public: + ValueArray37(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), + v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), + v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), + v36_(v36), v37_(v37) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray37& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; +}; + +template +class ValueArray38 { + public: + ValueArray38(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray38& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; +}; + +template +class ValueArray39 { + public: + ValueArray39(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray39& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; +}; + +template +class ValueArray40 { + public: + ValueArray40(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), + v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), + v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), + v40_(v40) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray40& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; +}; + +template +class ValueArray41 { + public: + ValueArray41(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, + T41 v41) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray41& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; +}; + +template +class ValueArray42 { + public: + ValueArray42(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41), v42_(v42) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray42& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; +}; + +template +class ValueArray43 { + public: + ValueArray43(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), + v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), + v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), + v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), + v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray43& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; +}; + +template +class ValueArray44 { + public: + ValueArray44(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), + v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), + v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), + v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), + v43_(v43), v44_(v44) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray44& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; +}; + +template +class ValueArray45 { + public: + ValueArray45(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), + v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), + v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), + v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), + v42_(v42), v43_(v43), v44_(v44), v45_(v45) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray45& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; +}; + +template +class ValueArray46 { + public: + ValueArray46(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), + v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray46& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; +}; + +template +class ValueArray47 { + public: + ValueArray47(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), + v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46), + v47_(v47) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_), static_cast(v47_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray47& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; +}; + +template +class ValueArray48 { + public: + ValueArray48(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), + v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), + v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), + v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), + v46_(v46), v47_(v47), v48_(v48) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_), static_cast(v47_), + static_cast(v48_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray48& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; + const T48 v48_; +}; + +template +class ValueArray49 { + public: + ValueArray49(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, + T49 v49) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), + v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_), static_cast(v47_), + static_cast(v48_), static_cast(v49_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray49& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; + const T48 v48_; + const T49 v49_; +}; + +template +class ValueArray50 { + public: + ValueArray50(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, T49 v49, + T50 v50) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), + v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49), v50_(v50) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_), static_cast(v47_), + static_cast(v48_), static_cast(v49_), static_cast(v50_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray50& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; + const T48 v48_; + const T49 v49_; + const T50 v50_; +}; + +# if GTEST_HAS_COMBINE +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Generates values from the Cartesian product of values produced +// by the argument generators. +// +template +class CartesianProductGenerator2 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator2(const ParamGenerator& g1, + const ParamGenerator& g2) + : g1_(g1), g2_(g2) {} + virtual ~CartesianProductGenerator2() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current2_; + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + ParamType current_value_; + }; // class CartesianProductGenerator2::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator2& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; +}; // class CartesianProductGenerator2 + + +template +class CartesianProductGenerator3 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator3(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3) + : g1_(g1), g2_(g2), g3_(g3) {} + virtual ~CartesianProductGenerator3() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current3_; + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + ParamType current_value_; + }; // class CartesianProductGenerator3::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator3& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; +}; // class CartesianProductGenerator3 + + +template +class CartesianProductGenerator4 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator4(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {} + virtual ~CartesianProductGenerator4() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current4_; + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + ParamType current_value_; + }; // class CartesianProductGenerator4::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator4& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; +}; // class CartesianProductGenerator4 + + +template +class CartesianProductGenerator5 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator5(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {} + virtual ~CartesianProductGenerator5() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current5_; + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + ParamType current_value_; + }; // class CartesianProductGenerator5::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator5& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; +}; // class CartesianProductGenerator5 + + +template +class CartesianProductGenerator6 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator6(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {} + virtual ~CartesianProductGenerator6() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current6_; + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + ParamType current_value_; + }; // class CartesianProductGenerator6::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator6& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; +}; // class CartesianProductGenerator6 + + +template +class CartesianProductGenerator7 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator7(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {} + virtual ~CartesianProductGenerator7() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current7_; + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + ParamType current_value_; + }; // class CartesianProductGenerator7::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator7& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; +}; // class CartesianProductGenerator7 + + +template +class CartesianProductGenerator8 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator8(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7, + const ParamGenerator& g8) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), + g8_(g8) {} + virtual ~CartesianProductGenerator8() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin(), g8_, g8_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, + g8_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7, + const ParamGenerator& g8, + const typename ParamGenerator::iterator& current8) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7), + begin8_(g8.begin()), end8_(g8.end()), current8_(current8) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current8_; + if (current8_ == end8_) { + current8_ = begin8_; + ++current7_; + } + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_ && + current8_ == typed_other->current8_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_), + begin8_(other.begin8_), + end8_(other.end8_), + current8_(other.current8_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_, *current8_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_ || + current8_ == end8_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + const typename ParamGenerator::iterator begin8_; + const typename ParamGenerator::iterator end8_; + typename ParamGenerator::iterator current8_; + ParamType current_value_; + }; // class CartesianProductGenerator8::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator8& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; + const ParamGenerator g8_; +}; // class CartesianProductGenerator8 + + +template +class CartesianProductGenerator9 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator9(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7, + const ParamGenerator& g8, const ParamGenerator& g9) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9) {} + virtual ~CartesianProductGenerator9() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, + g8_.end(), g9_, g9_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7, + const ParamGenerator& g8, + const typename ParamGenerator::iterator& current8, + const ParamGenerator& g9, + const typename ParamGenerator::iterator& current9) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7), + begin8_(g8.begin()), end8_(g8.end()), current8_(current8), + begin9_(g9.begin()), end9_(g9.end()), current9_(current9) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current9_; + if (current9_ == end9_) { + current9_ = begin9_; + ++current8_; + } + if (current8_ == end8_) { + current8_ = begin8_; + ++current7_; + } + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_ && + current8_ == typed_other->current8_ && + current9_ == typed_other->current9_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_), + begin8_(other.begin8_), + end8_(other.end8_), + current8_(other.current8_), + begin9_(other.begin9_), + end9_(other.end9_), + current9_(other.current9_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_, *current8_, + *current9_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_ || + current8_ == end8_ || + current9_ == end9_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + const typename ParamGenerator::iterator begin8_; + const typename ParamGenerator::iterator end8_; + typename ParamGenerator::iterator current8_; + const typename ParamGenerator::iterator begin9_; + const typename ParamGenerator::iterator end9_; + typename ParamGenerator::iterator current9_; + ParamType current_value_; + }; // class CartesianProductGenerator9::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator9& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; + const ParamGenerator g8_; + const ParamGenerator g9_; +}; // class CartesianProductGenerator9 + + +template +class CartesianProductGenerator10 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator10(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7, + const ParamGenerator& g8, const ParamGenerator& g9, + const ParamGenerator& g10) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9), g10_(g10) {} + virtual ~CartesianProductGenerator10() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin(), g10_, g10_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, + g8_.end(), g9_, g9_.end(), g10_, g10_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7, + const ParamGenerator& g8, + const typename ParamGenerator::iterator& current8, + const ParamGenerator& g9, + const typename ParamGenerator::iterator& current9, + const ParamGenerator& g10, + const typename ParamGenerator::iterator& current10) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7), + begin8_(g8.begin()), end8_(g8.end()), current8_(current8), + begin9_(g9.begin()), end9_(g9.end()), current9_(current9), + begin10_(g10.begin()), end10_(g10.end()), current10_(current10) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current10_; + if (current10_ == end10_) { + current10_ = begin10_; + ++current9_; + } + if (current9_ == end9_) { + current9_ = begin9_; + ++current8_; + } + if (current8_ == end8_) { + current8_ = begin8_; + ++current7_; + } + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_ && + current8_ == typed_other->current8_ && + current9_ == typed_other->current9_ && + current10_ == typed_other->current10_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_), + begin8_(other.begin8_), + end8_(other.end8_), + current8_(other.current8_), + begin9_(other.begin9_), + end9_(other.end9_), + current9_(other.current9_), + begin10_(other.begin10_), + end10_(other.end10_), + current10_(other.current10_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_, *current8_, + *current9_, *current10_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_ || + current8_ == end8_ || + current9_ == end9_ || + current10_ == end10_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + const typename ParamGenerator::iterator begin8_; + const typename ParamGenerator::iterator end8_; + typename ParamGenerator::iterator current8_; + const typename ParamGenerator::iterator begin9_; + const typename ParamGenerator::iterator end9_; + typename ParamGenerator::iterator current9_; + const typename ParamGenerator::iterator begin10_; + const typename ParamGenerator::iterator end10_; + typename ParamGenerator::iterator current10_; + ParamType current_value_; + }; // class CartesianProductGenerator10::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator10& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; + const ParamGenerator g8_; + const ParamGenerator g9_; + const ParamGenerator g10_; +}; // class CartesianProductGenerator10 + + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Helper classes providing Combine() with polymorphic features. They allow +// casting CartesianProductGeneratorN to ParamGenerator if T is +// convertible to U. +// +template +class CartesianProductHolder2 { + public: +CartesianProductHolder2(const Generator1& g1, const Generator2& g2) + : g1_(g1), g2_(g2) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator2( + static_cast >(g1_), + static_cast >(g2_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder2& other); + + const Generator1 g1_; + const Generator2 g2_; +}; // class CartesianProductHolder2 + +template +class CartesianProductHolder3 { + public: +CartesianProductHolder3(const Generator1& g1, const Generator2& g2, + const Generator3& g3) + : g1_(g1), g2_(g2), g3_(g3) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator3( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder3& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; +}; // class CartesianProductHolder3 + +template +class CartesianProductHolder4 { + public: +CartesianProductHolder4(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator4( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder4& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; +}; // class CartesianProductHolder4 + +template +class CartesianProductHolder5 { + public: +CartesianProductHolder5(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator5( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder5& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; +}; // class CartesianProductHolder5 + +template +class CartesianProductHolder6 { + public: +CartesianProductHolder6(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator6( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder6& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; +}; // class CartesianProductHolder6 + +template +class CartesianProductHolder7 { + public: +CartesianProductHolder7(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator7( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder7& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; +}; // class CartesianProductHolder7 + +template +class CartesianProductHolder8 { + public: +CartesianProductHolder8(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7, const Generator8& g8) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), + g8_(g8) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator8( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_), + static_cast >(g8_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder8& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; + const Generator8 g8_; +}; // class CartesianProductHolder8 + +template +class CartesianProductHolder9 { + public: +CartesianProductHolder9(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7, const Generator8& g8, + const Generator9& g9) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator9( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_), + static_cast >(g8_), + static_cast >(g9_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder9& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; + const Generator8 g8_; + const Generator9 g9_; +}; // class CartesianProductHolder9 + +template +class CartesianProductHolder10 { + public: +CartesianProductHolder10(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7, const Generator8& g8, + const Generator9& g9, const Generator10& g10) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9), g10_(g10) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator10( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_), + static_cast >(g8_), + static_cast >(g9_), + static_cast >(g10_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder10& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; + const Generator8 g8_; + const Generator9 g9_; + const Generator10 g10_; +}; // class CartesianProductHolder10 + +# endif // GTEST_HAS_COMBINE + +} // namespace internal +} // namespace testing + +#endif // GTEST_HAS_PARAM_TEST + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ + +#if GTEST_HAS_PARAM_TEST + +namespace testing { + +// Functions producing parameter generators. +// +// Google Test uses these generators to produce parameters for value- +// parameterized tests. When a parameterized test case is instantiated +// with a particular generator, Google Test creates and runs tests +// for each element in the sequence produced by the generator. +// +// In the following sample, tests from test case FooTest are instantiated +// each three times with parameter values 3, 5, and 8: +// +// class FooTest : public TestWithParam { ... }; +// +// TEST_P(FooTest, TestThis) { +// } +// TEST_P(FooTest, TestThat) { +// } +// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8)); +// + +// Range() returns generators providing sequences of values in a range. +// +// Synopsis: +// Range(start, end) +// - returns a generator producing a sequence of values {start, start+1, +// start+2, ..., }. +// Range(start, end, step) +// - returns a generator producing a sequence of values {start, start+step, +// start+step+step, ..., }. +// Notes: +// * The generated sequences never include end. For example, Range(1, 5) +// returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2) +// returns a generator producing {1, 3, 5, 7}. +// * start and end must have the same type. That type may be any integral or +// floating-point type or a user defined type satisfying these conditions: +// * It must be assignable (have operator=() defined). +// * It must have operator+() (operator+(int-compatible type) for +// two-operand version). +// * It must have operator<() defined. +// Elements in the resulting sequences will also have that type. +// * Condition start < end must be satisfied in order for resulting sequences +// to contain any elements. +// +template +internal::ParamGenerator Range(T start, T end, IncrementT step) { + return internal::ParamGenerator( + new internal::RangeGenerator(start, end, step)); +} + +template +internal::ParamGenerator Range(T start, T end) { + return Range(start, end, 1); +} + +// ValuesIn() function allows generation of tests with parameters coming from +// a container. +// +// Synopsis: +// ValuesIn(const T (&array)[N]) +// - returns a generator producing sequences with elements from +// a C-style array. +// ValuesIn(const Container& container) +// - returns a generator producing sequences with elements from +// an STL-style container. +// ValuesIn(Iterator begin, Iterator end) +// - returns a generator producing sequences with elements from +// a range [begin, end) defined by a pair of STL-style iterators. These +// iterators can also be plain C pointers. +// +// Please note that ValuesIn copies the values from the containers +// passed in and keeps them to generate tests in RUN_ALL_TESTS(). +// +// Examples: +// +// This instantiates tests from test case StringTest +// each with C-string values of "foo", "bar", and "baz": +// +// const char* strings[] = {"foo", "bar", "baz"}; +// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings)); +// +// This instantiates tests from test case StlStringTest +// each with STL strings with values "a" and "b": +// +// ::std::vector< ::std::string> GetParameterStrings() { +// ::std::vector< ::std::string> v; +// v.push_back("a"); +// v.push_back("b"); +// return v; +// } +// +// INSTANTIATE_TEST_CASE_P(CharSequence, +// StlStringTest, +// ValuesIn(GetParameterStrings())); +// +// +// This will also instantiate tests from CharTest +// each with parameter values 'a' and 'b': +// +// ::std::list GetParameterChars() { +// ::std::list list; +// list.push_back('a'); +// list.push_back('b'); +// return list; +// } +// ::std::list l = GetParameterChars(); +// INSTANTIATE_TEST_CASE_P(CharSequence2, +// CharTest, +// ValuesIn(l.begin(), l.end())); +// +template +internal::ParamGenerator< + typename ::testing::internal::IteratorTraits::value_type> +ValuesIn(ForwardIterator begin, ForwardIterator end) { + typedef typename ::testing::internal::IteratorTraits + ::value_type ParamType; + return internal::ParamGenerator( + new internal::ValuesInIteratorRangeGenerator(begin, end)); +} + +template +internal::ParamGenerator ValuesIn(const T (&array)[N]) { + return ValuesIn(array, array + N); +} + +template +internal::ParamGenerator ValuesIn( + const Container& container) { + return ValuesIn(container.begin(), container.end()); +} + +// Values() allows generating tests from explicitly specified list of +// parameters. +// +// Synopsis: +// Values(T v1, T v2, ..., T vN) +// - returns a generator producing sequences with elements v1, v2, ..., vN. +// +// For example, this instantiates tests from test case BarTest each +// with values "one", "two", and "three": +// +// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three")); +// +// This instantiates tests from test case BazTest each with values 1, 2, 3.5. +// The exact type of values will depend on the type of parameter in BazTest. +// +// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5)); +// +// Currently, Values() supports from 1 to 50 parameters. +// +template +internal::ValueArray1 Values(T1 v1) { + return internal::ValueArray1(v1); +} + +template +internal::ValueArray2 Values(T1 v1, T2 v2) { + return internal::ValueArray2(v1, v2); +} + +template +internal::ValueArray3 Values(T1 v1, T2 v2, T3 v3) { + return internal::ValueArray3(v1, v2, v3); +} + +template +internal::ValueArray4 Values(T1 v1, T2 v2, T3 v3, T4 v4) { + return internal::ValueArray4(v1, v2, v3, v4); +} + +template +internal::ValueArray5 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5) { + return internal::ValueArray5(v1, v2, v3, v4, v5); +} + +template +internal::ValueArray6 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6) { + return internal::ValueArray6(v1, v2, v3, v4, v5, v6); +} + +template +internal::ValueArray7 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6, T7 v7) { + return internal::ValueArray7(v1, v2, v3, v4, v5, + v6, v7); +} + +template +internal::ValueArray8 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8) { + return internal::ValueArray8(v1, v2, v3, v4, + v5, v6, v7, v8); +} + +template +internal::ValueArray9 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9) { + return internal::ValueArray9(v1, v2, v3, + v4, v5, v6, v7, v8, v9); +} + +template +internal::ValueArray10 Values(T1 v1, + T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10) { + return internal::ValueArray10(v1, + v2, v3, v4, v5, v6, v7, v8, v9, v10); +} + +template +internal::ValueArray11 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11) { + return internal::ValueArray11(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11); +} + +template +internal::ValueArray12 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12) { + return internal::ValueArray12(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12); +} + +template +internal::ValueArray13 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13) { + return internal::ValueArray13(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13); +} + +template +internal::ValueArray14 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) { + return internal::ValueArray14(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, + v14); +} + +template +internal::ValueArray15 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) { + return internal::ValueArray15(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, + v13, v14, v15); +} + +template +internal::ValueArray16 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16) { + return internal::ValueArray16(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, + v12, v13, v14, v15, v16); +} + +template +internal::ValueArray17 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17) { + return internal::ValueArray17(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, + v11, v12, v13, v14, v15, v16, v17); +} + +template +internal::ValueArray18 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, + T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18) { + return internal::ValueArray18(v1, v2, v3, v4, v5, v6, v7, v8, v9, + v10, v11, v12, v13, v14, v15, v16, v17, v18); +} + +template +internal::ValueArray19 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, + T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, + T15 v15, T16 v16, T17 v17, T18 v18, T19 v19) { + return internal::ValueArray19(v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19); +} + +template +internal::ValueArray20 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20) { + return internal::ValueArray20(v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20); +} + +template +internal::ValueArray21 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21) { + return internal::ValueArray21(v1, v2, v3, v4, v5, v6, + v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21); +} + +template +internal::ValueArray22 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22) { + return internal::ValueArray22(v1, v2, v3, v4, + v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22); +} + +template +internal::ValueArray23 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23) { + return internal::ValueArray23(v1, v2, v3, + v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23); +} + +template +internal::ValueArray24 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24) { + return internal::ValueArray24(v1, v2, + v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, + v19, v20, v21, v22, v23, v24); +} + +template +internal::ValueArray25 Values(T1 v1, + T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, + T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, + T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25) { + return internal::ValueArray25(v1, + v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, + v18, v19, v20, v21, v22, v23, v24, v25); +} + +template +internal::ValueArray26 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26) { + return internal::ValueArray26(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, + v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26); +} + +template +internal::ValueArray27 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27) { + return internal::ValueArray27(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, + v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27); +} + +template +internal::ValueArray28 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28) { + return internal::ValueArray28(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, + v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, + v28); +} + +template +internal::ValueArray29 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29) { + return internal::ValueArray29(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, + v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, + v27, v28, v29); +} + +template +internal::ValueArray30 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, + T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, + T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) { + return internal::ValueArray30(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, + v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, + v26, v27, v28, v29, v30); +} + +template +internal::ValueArray31 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) { + return internal::ValueArray31(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, + v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, + v25, v26, v27, v28, v29, v30, v31); +} + +template +internal::ValueArray32 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32) { + return internal::ValueArray32(v1, v2, v3, v4, v5, v6, v7, v8, v9, + v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32); +} + +template +internal::ValueArray33 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, + T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33) { + return internal::ValueArray33(v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32, v33); +} + +template +internal::ValueArray34 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, + T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, + T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, + T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, + T31 v31, T32 v32, T33 v33, T34 v34) { + return internal::ValueArray34(v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, + v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34); +} + +template +internal::ValueArray35 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, + T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, + T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35) { + return internal::ValueArray35(v1, v2, v3, v4, v5, v6, + v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, + v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35); +} + +template +internal::ValueArray36 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, + T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, + T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36) { + return internal::ValueArray36(v1, v2, v3, v4, + v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, + v34, v35, v36); +} + +template +internal::ValueArray37 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, + T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, + T37 v37) { + return internal::ValueArray37(v1, v2, v3, + v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, + v34, v35, v36, v37); +} + +template +internal::ValueArray38 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, + T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, + T37 v37, T38 v38) { + return internal::ValueArray38(v1, v2, + v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, + v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, + v33, v34, v35, v36, v37, v38); +} + +template +internal::ValueArray39 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, + T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, + T37 v37, T38 v38, T39 v39) { + return internal::ValueArray39(v1, + v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, + v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, + v32, v33, v34, v35, v36, v37, v38, v39); +} + +template +internal::ValueArray40 Values(T1 v1, + T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, + T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, + T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, + T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, + T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) { + return internal::ValueArray40(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, + v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, + v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40); +} + +template +internal::ValueArray41 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41) { + return internal::ValueArray41(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, + v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, + v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41); +} + +template +internal::ValueArray42 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42) { + return internal::ValueArray42(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, + v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, + v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, + v42); +} + +template +internal::ValueArray43 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43) { + return internal::ValueArray43(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, + v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, + v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, + v41, v42, v43); +} + +template +internal::ValueArray44 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44) { + return internal::ValueArray44(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, + v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, + v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, + v40, v41, v42, v43, v44); +} + +template +internal::ValueArray45 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, + T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, + T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, + T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, + T41 v41, T42 v42, T43 v43, T44 v44, T45 v45) { + return internal::ValueArray45(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, + v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, + v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, + v39, v40, v41, v42, v43, v44, v45); +} + +template +internal::ValueArray46 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, + T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) { + return internal::ValueArray46(v1, v2, v3, v4, v5, v6, v7, v8, v9, + v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, + v38, v39, v40, v41, v42, v43, v44, v45, v46); +} + +template +internal::ValueArray47 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, + T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) { + return internal::ValueArray47(v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, + v38, v39, v40, v41, v42, v43, v44, v45, v46, v47); +} + +template +internal::ValueArray48 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, + T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, + T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, + T48 v48) { + return internal::ValueArray48(v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, + v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, + v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48); +} + +template +internal::ValueArray49 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, + T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, + T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, + T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, + T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, + T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, + T47 v47, T48 v48, T49 v49) { + return internal::ValueArray49(v1, v2, v3, v4, v5, v6, + v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, + v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, + v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49); +} + +template +internal::ValueArray50 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, + T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, + T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, + T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, + T46 v46, T47 v47, T48 v48, T49 v49, T50 v50) { + return internal::ValueArray50(v1, v2, v3, v4, + v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, + v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, + v48, v49, v50); +} + +// Bool() allows generating tests with parameters in a set of (false, true). +// +// Synopsis: +// Bool() +// - returns a generator producing sequences with elements {false, true}. +// +// It is useful when testing code that depends on Boolean flags. Combinations +// of multiple flags can be tested when several Bool()'s are combined using +// Combine() function. +// +// In the following example all tests in the test case FlagDependentTest +// will be instantiated twice with parameters false and true. +// +// class FlagDependentTest : public testing::TestWithParam { +// virtual void SetUp() { +// external_flag = GetParam(); +// } +// } +// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool()); +// +inline internal::ParamGenerator Bool() { + return Values(false, true); +} + +# if GTEST_HAS_COMBINE +// Combine() allows the user to combine two or more sequences to produce +// values of a Cartesian product of those sequences' elements. +// +// Synopsis: +// Combine(gen1, gen2, ..., genN) +// - returns a generator producing sequences with elements coming from +// the Cartesian product of elements from the sequences generated by +// gen1, gen2, ..., genN. The sequence elements will have a type of +// tuple where T1, T2, ..., TN are the types +// of elements from sequences produces by gen1, gen2, ..., genN. +// +// Combine can have up to 10 arguments. This number is currently limited +// by the maximum number of elements in the tuple implementation used by Google +// Test. +// +// Example: +// +// This will instantiate tests in test case AnimalTest each one with +// the parameter values tuple("cat", BLACK), tuple("cat", WHITE), +// tuple("dog", BLACK), and tuple("dog", WHITE): +// +// enum Color { BLACK, GRAY, WHITE }; +// class AnimalTest +// : public testing::TestWithParam > {...}; +// +// TEST_P(AnimalTest, AnimalLooksNice) {...} +// +// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest, +// Combine(Values("cat", "dog"), +// Values(BLACK, WHITE))); +// +// This will instantiate tests in FlagDependentTest with all variations of two +// Boolean flags: +// +// class FlagDependentTest +// : public testing::TestWithParam > { +// virtual void SetUp() { +// // Assigns external_flag_1 and external_flag_2 values from the tuple. +// tie(external_flag_1, external_flag_2) = GetParam(); +// } +// }; +// +// TEST_P(FlagDependentTest, TestFeature1) { +// // Test your code using external_flag_1 and external_flag_2 here. +// } +// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest, +// Combine(Bool(), Bool())); +// +template +internal::CartesianProductHolder2 Combine( + const Generator1& g1, const Generator2& g2) { + return internal::CartesianProductHolder2( + g1, g2); +} + +template +internal::CartesianProductHolder3 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3) { + return internal::CartesianProductHolder3( + g1, g2, g3); +} + +template +internal::CartesianProductHolder4 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4) { + return internal::CartesianProductHolder4( + g1, g2, g3, g4); +} + +template +internal::CartesianProductHolder5 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5) { + return internal::CartesianProductHolder5( + g1, g2, g3, g4, g5); +} + +template +internal::CartesianProductHolder6 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6) { + return internal::CartesianProductHolder6( + g1, g2, g3, g4, g5, g6); +} + +template +internal::CartesianProductHolder7 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7) { + return internal::CartesianProductHolder7( + g1, g2, g3, g4, g5, g6, g7); +} + +template +internal::CartesianProductHolder8 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7, const Generator8& g8) { + return internal::CartesianProductHolder8( + g1, g2, g3, g4, g5, g6, g7, g8); +} + +template +internal::CartesianProductHolder9 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7, const Generator8& g8, const Generator9& g9) { + return internal::CartesianProductHolder9( + g1, g2, g3, g4, g5, g6, g7, g8, g9); +} + +template +internal::CartesianProductHolder10 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7, const Generator8& g8, const Generator9& g9, + const Generator10& g10) { + return internal::CartesianProductHolder10( + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10); +} +# endif // GTEST_HAS_COMBINE + + + +# define TEST_P(test_case_name, test_name) \ + class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ + : public test_case_name { \ + public: \ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \ + virtual void TestBody(); \ + private: \ + static int AddToRegistry() { \ + ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ + GetTestCasePatternHolder(\ + #test_case_name, __FILE__, __LINE__)->AddTestPattern(\ + #test_case_name, \ + #test_name, \ + new ::testing::internal::TestMetaFactory< \ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \ + return 0; \ + } \ + static int gtest_registering_dummy_; \ + GTEST_DISALLOW_COPY_AND_ASSIGN_(\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \ + }; \ + int GTEST_TEST_CLASS_NAME_(test_case_name, \ + test_name)::gtest_registering_dummy_ = \ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \ + void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() + +# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \ + ::testing::internal::ParamGenerator \ + gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \ + int gtest_##prefix##test_case_name##_dummy_ = \ + ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ + GetTestCasePatternHolder(\ + #test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\ + #prefix, \ + >est_##prefix##test_case_name##_EvalGenerator_, \ + __FILE__, __LINE__) + +} // namespace testing + +#endif // GTEST_HAS_PARAM_TEST + +#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ +// Copyright 2006, 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) +// +// Google C++ Testing Framework definitions useful in production code. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_ + +// When you need to test the private or protected members of a class, +// use the FRIEND_TEST macro to declare your tests as friends of the +// class. For example: +// +// class MyClass { +// private: +// void MyMethod(); +// FRIEND_TEST(MyClassTest, MyMethod); +// }; +// +// class MyClassTest : public testing::Test { +// // ... +// }; +// +// TEST_F(MyClassTest, MyMethod) { +// // Can call MyClass::MyMethod() here. +// } + +#define FRIEND_TEST(test_case_name, test_name)\ +friend class test_case_name##_##test_name##_Test + +#endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_ +// Copyright 2008, 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: mheule@google.com (Markus Heule) +// + +#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ +#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ + +#include +#include + +namespace testing { + +// A copyable object representing the result of a test part (i.e. an +// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()). +// +// Don't inherit from TestPartResult as its destructor is not virtual. +class GTEST_API_ TestPartResult { + public: + // The possible outcomes of a test part (i.e. an assertion or an + // explicit SUCCEED(), FAIL(), or ADD_FAILURE()). + enum Type { + kSuccess, // Succeeded. + kNonFatalFailure, // Failed but the test can continue. + kFatalFailure // Failed and the test should be terminated. + }; + + // C'tor. TestPartResult does NOT have a default constructor. + // Always use this constructor (with parameters) to create a + // TestPartResult object. + TestPartResult(Type a_type, + const char* a_file_name, + int a_line_number, + const char* a_message) + : type_(a_type), + file_name_(a_file_name == NULL ? "" : a_file_name), + line_number_(a_line_number), + summary_(ExtractSummary(a_message)), + message_(a_message) { + } + + // Gets the outcome of the test part. + Type type() const { return type_; } + + // Gets the name of the source file where the test part took place, or + // NULL if it's unknown. + const char* file_name() const { + return file_name_.empty() ? NULL : file_name_.c_str(); + } + + // Gets the line in the source file where the test part took place, + // or -1 if it's unknown. + int line_number() const { return line_number_; } + + // Gets the summary of the failure message. + const char* summary() const { return summary_.c_str(); } + + // Gets the message associated with the test part. + const char* message() const { return message_.c_str(); } + + // Returns true iff the test part passed. + bool passed() const { return type_ == kSuccess; } + + // Returns true iff the test part failed. + bool failed() const { return type_ != kSuccess; } + + // Returns true iff the test part non-fatally failed. + bool nonfatally_failed() const { return type_ == kNonFatalFailure; } + + // Returns true iff the test part fatally failed. + bool fatally_failed() const { return type_ == kFatalFailure; } + + private: + Type type_; + + // Gets the summary of the failure message by omitting the stack + // trace in it. + static std::string ExtractSummary(const char* message); + + // The name of the source file where the test part took place, or + // "" if the source file is unknown. + std::string file_name_; + // The line in the source file where the test part took place, or -1 + // if the line number is unknown. + int line_number_; + std::string summary_; // The test failure summary. + std::string message_; // The test failure message. +}; + +// Prints a TestPartResult object. +std::ostream& operator<<(std::ostream& os, const TestPartResult& result); + +// An array of TestPartResult objects. +// +// Don't inherit from TestPartResultArray as its destructor is not +// virtual. +class GTEST_API_ TestPartResultArray { + public: + TestPartResultArray() {} + + // Appends the given TestPartResult to the array. + void Append(const TestPartResult& result); + + // Returns the TestPartResult at the given index (0-based). + const TestPartResult& GetTestPartResult(int index) const; + + // Returns the number of TestPartResult objects in the array. + int size() const; + + private: + std::vector array_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray); +}; + +// This interface knows how to report a test part result. +class TestPartResultReporterInterface { + public: + virtual ~TestPartResultReporterInterface() {} + + virtual void ReportTestPartResult(const TestPartResult& result) = 0; +}; + +namespace internal { + +// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a +// statement generates new fatal failures. To do so it registers itself as the +// current test part result reporter. Besides checking if fatal failures were +// reported, it only delegates the reporting to the former result reporter. +// The original result reporter is restored in the destructor. +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +class GTEST_API_ HasNewFatalFailureHelper + : public TestPartResultReporterInterface { + public: + HasNewFatalFailureHelper(); + virtual ~HasNewFatalFailureHelper(); + virtual void ReportTestPartResult(const TestPartResult& result); + bool has_new_fatal_failure() const { return has_new_fatal_failure_; } + private: + bool has_new_fatal_failure_; + TestPartResultReporterInterface* original_reporter_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper); +}; + +} // namespace internal + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ +// Copyright 2008 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) + +#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ + +// This header implements typed tests and type-parameterized tests. + +// Typed (aka type-driven) tests repeat the same test for types in a +// list. You must know which types you want to test with when writing +// typed tests. Here's how you do it: + +#if 0 + +// First, define a fixture class template. It should be parameterized +// by a type. Remember to derive it from testing::Test. +template +class FooTest : public testing::Test { + public: + ... + typedef std::list List; + static T shared_; + T value_; +}; + +// Next, associate a list of types with the test case, which will be +// repeated for each type in the list. The typedef is necessary for +// the macro to parse correctly. +typedef testing::Types MyTypes; +TYPED_TEST_CASE(FooTest, MyTypes); + +// If the type list contains only one type, you can write that type +// directly without Types<...>: +// TYPED_TEST_CASE(FooTest, int); + +// Then, use TYPED_TEST() instead of TEST_F() to define as many typed +// tests for this test case as you want. +TYPED_TEST(FooTest, DoesBlah) { + // Inside a test, refer to TypeParam to get the type parameter. + // Since we are inside a derived class template, C++ requires use to + // visit the members of FooTest via 'this'. + TypeParam n = this->value_; + + // To visit static members of the fixture, add the TestFixture:: + // prefix. + n += TestFixture::shared_; + + // To refer to typedefs in the fixture, add the "typename + // TestFixture::" prefix. + typename TestFixture::List values; + values.push_back(n); + ... +} + +TYPED_TEST(FooTest, HasPropertyA) { ... } + +#endif // 0 + +// Type-parameterized tests are abstract test patterns parameterized +// by a type. Compared with typed tests, type-parameterized tests +// allow you to define the test pattern without knowing what the type +// parameters are. The defined pattern can be instantiated with +// different types any number of times, in any number of translation +// units. +// +// If you are designing an interface or concept, you can define a +// suite of type-parameterized tests to verify properties that any +// valid implementation of the interface/concept should have. Then, +// each implementation can easily instantiate the test suite to verify +// that it conforms to the requirements, without having to write +// similar tests repeatedly. Here's an example: + +#if 0 + +// First, define a fixture class template. It should be parameterized +// by a type. Remember to derive it from testing::Test. +template +class FooTest : public testing::Test { + ... +}; + +// Next, declare that you will define a type-parameterized test case +// (the _P suffix is for "parameterized" or "pattern", whichever you +// prefer): +TYPED_TEST_CASE_P(FooTest); + +// Then, use TYPED_TEST_P() to define as many type-parameterized tests +// for this type-parameterized test case as you want. +TYPED_TEST_P(FooTest, DoesBlah) { + // Inside a test, refer to TypeParam to get the type parameter. + TypeParam n = 0; + ... +} + +TYPED_TEST_P(FooTest, HasPropertyA) { ... } + +// Now the tricky part: you need to register all test patterns before +// you can instantiate them. The first argument of the macro is the +// test case name; the rest are the names of the tests in this test +// case. +REGISTER_TYPED_TEST_CASE_P(FooTest, + DoesBlah, HasPropertyA); + +// Finally, you are free to instantiate the pattern with the types you +// want. If you put the above code in a header file, you can #include +// it in multiple C++ source files and instantiate it multiple times. +// +// To distinguish different instances of the pattern, the first +// argument to the INSTANTIATE_* macro is a prefix that will be added +// to the actual test case name. Remember to pick unique prefixes for +// different instances. +typedef testing::Types MyTypes; +INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes); + +// If the type list contains only one type, you can write that type +// directly without Types<...>: +// INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int); + +#endif // 0 + + +// Implements typed tests. + +#if GTEST_HAS_TYPED_TEST + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Expands to the name of the typedef for the type parameters of the +// given test case. +# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_ + +// The 'Types' template argument below must have spaces around it +// since some compilers may choke on '>>' when passing a template +// instance (e.g. Types) +# define TYPED_TEST_CASE(CaseName, Types) \ + typedef ::testing::internal::TypeList< Types >::type \ + GTEST_TYPE_PARAMS_(CaseName) + +# define TYPED_TEST(CaseName, TestName) \ + template \ + class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \ + : public CaseName { \ + private: \ + typedef CaseName TestFixture; \ + typedef gtest_TypeParam_ TypeParam; \ + virtual void TestBody(); \ + }; \ + bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \ + ::testing::internal::TypeParameterizedTest< \ + CaseName, \ + ::testing::internal::TemplateSel< \ + GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \ + GTEST_TYPE_PARAMS_(CaseName)>::Register(\ + "", #CaseName, #TestName, 0); \ + template \ + void GTEST_TEST_CLASS_NAME_(CaseName, TestName)::TestBody() + +#endif // GTEST_HAS_TYPED_TEST + +// Implements type-parameterized tests. + +#if GTEST_HAS_TYPED_TEST_P + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Expands to the namespace name that the type-parameterized tests for +// the given type-parameterized test case are defined in. The exact +// name of the namespace is subject to change without notice. +# define GTEST_CASE_NAMESPACE_(TestCaseName) \ + gtest_case_##TestCaseName##_ + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Expands to the name of the variable used to remember the names of +// the defined tests in the given test case. +# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \ + gtest_typed_test_case_p_state_##TestCaseName##_ + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY. +// +// Expands to the name of the variable used to remember the names of +// the registered tests in the given test case. +# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \ + gtest_registered_test_names_##TestCaseName##_ + +// The variables defined in the type-parameterized test macros are +// static as typically these macros are used in a .h file that can be +// #included in multiple translation units linked together. +# define TYPED_TEST_CASE_P(CaseName) \ + static ::testing::internal::TypedTestCasePState \ + GTEST_TYPED_TEST_CASE_P_STATE_(CaseName) + +# define TYPED_TEST_P(CaseName, TestName) \ + namespace GTEST_CASE_NAMESPACE_(CaseName) { \ + template \ + class TestName : public CaseName { \ + private: \ + typedef CaseName TestFixture; \ + typedef gtest_TypeParam_ TypeParam; \ + virtual void TestBody(); \ + }; \ + static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \ + GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\ + __FILE__, __LINE__, #CaseName, #TestName); \ + } \ + template \ + void GTEST_CASE_NAMESPACE_(CaseName)::TestName::TestBody() + +# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \ + namespace GTEST_CASE_NAMESPACE_(CaseName) { \ + typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \ + } \ + static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \ + GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\ + __FILE__, __LINE__, #__VA_ARGS__) + +// The 'Types' template argument below must have spaces around it +// since some compilers may choke on '>>' when passing a template +// instance (e.g. Types) +# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \ + bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \ + ::testing::internal::TypeParameterizedTestCase::type>::Register(\ + #Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName)) + +#endif // GTEST_HAS_TYPED_TEST_P + +#endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ + +// Depending on the platform, different string classes are available. +// On Linux, in addition to ::std::string, Google also makes use of +// class ::string, which has the same interface as ::std::string, but +// has a different implementation. +// +// The user can define GTEST_HAS_GLOBAL_STRING to 1 to indicate that +// ::string is available AND is a distinct type to ::std::string, or +// define it to 0 to indicate otherwise. +// +// If the user's ::std::string and ::string are the same class due to +// aliasing, he should define GTEST_HAS_GLOBAL_STRING to 0. +// +// If the user doesn't define GTEST_HAS_GLOBAL_STRING, it is defined +// heuristically. + +namespace testing { + +// Declares the flags. + +// This flag temporary enables the disabled tests. +GTEST_DECLARE_bool_(also_run_disabled_tests); + +// This flag brings the debugger on an assertion failure. +GTEST_DECLARE_bool_(break_on_failure); + +// This flag controls whether Google Test catches all test-thrown exceptions +// and logs them as failures. +GTEST_DECLARE_bool_(catch_exceptions); + +// This flag enables using colors in terminal output. Available values are +// "yes" to enable colors, "no" (disable colors), or "auto" (the default) +// to let Google Test decide. +GTEST_DECLARE_string_(color); + +// This flag sets up the filter to select by name using a glob pattern +// the tests to run. If the filter is not given all tests are executed. +GTEST_DECLARE_string_(filter); + +// This flag causes the Google Test to list tests. None of the tests listed +// are actually run if the flag is provided. +GTEST_DECLARE_bool_(list_tests); + +// This flag controls whether Google Test emits a detailed XML report to a file +// in addition to its normal textual output. +GTEST_DECLARE_string_(output); + +// This flags control whether Google Test prints the elapsed time for each +// test. +GTEST_DECLARE_bool_(print_time); + +// This flag specifies the random number seed. +GTEST_DECLARE_int32_(random_seed); + +// This flag sets how many times the tests are repeated. The default value +// is 1. If the value is -1 the tests are repeating forever. +GTEST_DECLARE_int32_(repeat); + +// This flag controls whether Google Test includes Google Test internal +// stack frames in failure stack traces. +GTEST_DECLARE_bool_(show_internal_stack_frames); + +// When this flag is specified, tests' order is randomized on every iteration. +GTEST_DECLARE_bool_(shuffle); + +// This flag specifies the maximum number of stack frames to be +// printed in a failure message. +GTEST_DECLARE_int32_(stack_trace_depth); + +// When this flag is specified, a failed assertion will throw an +// exception if exceptions are enabled, or exit the program with a +// non-zero code otherwise. +GTEST_DECLARE_bool_(throw_on_failure); + +// When this flag is set with a "host:port" string, on supported +// platforms test results are streamed to the specified port on +// the specified host machine. +GTEST_DECLARE_string_(stream_result_to); + +// The upper limit for valid stack trace depths. +const int kMaxStackTraceDepth = 100; + +namespace internal { + +class AssertHelper; +class DefaultGlobalTestPartResultReporter; +class ExecDeathTest; +class NoExecDeathTest; +class FinalSuccessChecker; +class GTestFlagSaver; +class StreamingListenerTest; +class TestResultAccessor; +class TestEventListenersAccessor; +class TestEventRepeater; +class UnitTestRecordPropertyTestHelper; +class WindowsDeathTest; +class UnitTestImpl* GetUnitTestImpl(); +void ReportFailureInUnknownLocation(TestPartResult::Type result_type, + const std::string& message); + +} // namespace internal + +// The friend relationship of some of these classes is cyclic. +// If we don't forward declare them the compiler might confuse the classes +// in friendship clauses with same named classes on the scope. +class Test; +class TestCase; +class TestInfo; +class UnitTest; + +// A class for indicating whether an assertion was successful. When +// the assertion wasn't successful, the AssertionResult object +// remembers a non-empty message that describes how it failed. +// +// To create an instance of this class, use one of the factory functions +// (AssertionSuccess() and AssertionFailure()). +// +// This class is useful for two purposes: +// 1. Defining predicate functions to be used with Boolean test assertions +// EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts +// 2. Defining predicate-format functions to be +// used with predicate assertions (ASSERT_PRED_FORMAT*, etc). +// +// For example, if you define IsEven predicate: +// +// testing::AssertionResult IsEven(int n) { +// if ((n % 2) == 0) +// return testing::AssertionSuccess(); +// else +// return testing::AssertionFailure() << n << " is odd"; +// } +// +// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5))) +// will print the message +// +// Value of: IsEven(Fib(5)) +// Actual: false (5 is odd) +// Expected: true +// +// instead of a more opaque +// +// Value of: IsEven(Fib(5)) +// Actual: false +// Expected: true +// +// in case IsEven is a simple Boolean predicate. +// +// If you expect your predicate to be reused and want to support informative +// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up +// about half as often as positive ones in our tests), supply messages for +// both success and failure cases: +// +// testing::AssertionResult IsEven(int n) { +// if ((n % 2) == 0) +// return testing::AssertionSuccess() << n << " is even"; +// else +// return testing::AssertionFailure() << n << " is odd"; +// } +// +// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print +// +// Value of: IsEven(Fib(6)) +// Actual: true (8 is even) +// Expected: false +// +// NB: Predicates that support negative Boolean assertions have reduced +// performance in positive ones so be careful not to use them in tests +// that have lots (tens of thousands) of positive Boolean assertions. +// +// To use this class with EXPECT_PRED_FORMAT assertions such as: +// +// // Verifies that Foo() returns an even number. +// EXPECT_PRED_FORMAT1(IsEven, Foo()); +// +// you need to define: +// +// testing::AssertionResult IsEven(const char* expr, int n) { +// if ((n % 2) == 0) +// return testing::AssertionSuccess(); +// else +// return testing::AssertionFailure() +// << "Expected: " << expr << " is even\n Actual: it's " << n; +// } +// +// If Foo() returns 5, you will see the following message: +// +// Expected: Foo() is even +// Actual: it's 5 +// +class GTEST_API_ AssertionResult { + public: + // Copy constructor. + // Used in EXPECT_TRUE/FALSE(assertion_result). + AssertionResult(const AssertionResult& other); + // Used in the EXPECT_TRUE/FALSE(bool_expression). + explicit AssertionResult(bool success) : success_(success) {} + + // Returns true iff the assertion succeeded. + operator bool() const { return success_; } // NOLINT + + // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. + AssertionResult operator!() const; + + // Returns the text streamed into this AssertionResult. Test assertions + // use it when they fail (i.e., the predicate's outcome doesn't match the + // assertion's expectation). When nothing has been streamed into the + // object, returns an empty string. + const char* message() const { + return message_.get() != NULL ? message_->c_str() : ""; + } + // TODO(vladl@google.com): Remove this after making sure no clients use it. + // Deprecated; please use message() instead. + const char* failure_message() const { return message(); } + + // Streams a custom failure message into this object. + template AssertionResult& operator<<(const T& value) { + AppendMessage(Message() << value); + return *this; + } + + // Allows streaming basic output manipulators such as endl or flush into + // this object. + AssertionResult& operator<<( + ::std::ostream& (*basic_manipulator)(::std::ostream& stream)) { + AppendMessage(Message() << basic_manipulator); + return *this; + } + + private: + // Appends the contents of message to message_. + void AppendMessage(const Message& a_message) { + if (message_.get() == NULL) + message_.reset(new ::std::string); + message_->append(a_message.GetString().c_str()); + } + + // Stores result of the assertion predicate. + bool success_; + // Stores the message describing the condition in case the expectation + // construct is not satisfied with the predicate's outcome. + // Referenced via a pointer to avoid taking too much stack frame space + // with test assertions. + internal::scoped_ptr< ::std::string> message_; + + GTEST_DISALLOW_ASSIGN_(AssertionResult); +}; + +// Makes a successful assertion result. +GTEST_API_ AssertionResult AssertionSuccess(); + +// Makes a failed assertion result. +GTEST_API_ AssertionResult AssertionFailure(); + +// Makes a failed assertion result with the given failure message. +// Deprecated; use AssertionFailure() << msg. +GTEST_API_ AssertionResult AssertionFailure(const Message& msg); + +// The abstract class that all tests inherit from. +// +// In Google Test, a unit test program contains one or many TestCases, and +// each TestCase contains one or many Tests. +// +// When you define a test using the TEST macro, you don't need to +// explicitly derive from Test - the TEST macro automatically does +// this for you. +// +// The only time you derive from Test is when defining a test fixture +// to be used a TEST_F. For example: +// +// class FooTest : public testing::Test { +// protected: +// virtual void SetUp() { ... } +// virtual void TearDown() { ... } +// ... +// }; +// +// TEST_F(FooTest, Bar) { ... } +// TEST_F(FooTest, Baz) { ... } +// +// Test is not copyable. +class GTEST_API_ Test { + public: + friend class TestInfo; + + // Defines types for pointers to functions that set up and tear down + // a test case. + typedef internal::SetUpTestCaseFunc SetUpTestCaseFunc; + typedef internal::TearDownTestCaseFunc TearDownTestCaseFunc; + + // The d'tor is virtual as we intend to inherit from Test. + virtual ~Test(); + + // Sets up the stuff shared by all tests in this test case. + // + // Google Test will call Foo::SetUpTestCase() before running the first + // test in test case Foo. Hence a sub-class can define its own + // SetUpTestCase() method to shadow the one defined in the super + // class. + static void SetUpTestCase() {} + + // Tears down the stuff shared by all tests in this test case. + // + // Google Test will call Foo::TearDownTestCase() after running the last + // test in test case Foo. Hence a sub-class can define its own + // TearDownTestCase() method to shadow the one defined in the super + // class. + static void TearDownTestCase() {} + + // Returns true iff the current test has a fatal failure. + static bool HasFatalFailure(); + + // Returns true iff the current test has a non-fatal failure. + static bool HasNonfatalFailure(); + + // Returns true iff the current test has a (either fatal or + // non-fatal) failure. + static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); } + + // Logs a property for the current test, test case, or for the entire + // invocation of the test program when used outside of the context of a + // test case. Only the last value for a given key is remembered. These + // are public static so they can be called from utility functions that are + // not members of the test fixture. Calls to RecordProperty made during + // lifespan of the test (from the moment its constructor starts to the + // moment its destructor finishes) will be output in XML as attributes of + // the element. Properties recorded from fixture's + // SetUpTestCase or TearDownTestCase are logged as attributes of the + // corresponding element. Calls to RecordProperty made in the + // global context (before or after invocation of RUN_ALL_TESTS and from + // SetUp/TearDown method of Environment objects registered with Google + // Test) will be output as attributes of the element. + static void RecordProperty(const std::string& key, const std::string& value); + static void RecordProperty(const std::string& key, int value); + + protected: + // Creates a Test object. + Test(); + + // Sets up the test fixture. + virtual void SetUp(); + + // Tears down the test fixture. + virtual void TearDown(); + + private: + // Returns true iff the current test has the same fixture class as + // the first test in the current test case. + static bool HasSameFixtureClass(); + + // Runs the test after the test fixture has been set up. + // + // A sub-class must implement this to define the test logic. + // + // DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM. + // Instead, use the TEST or TEST_F macro. + virtual void TestBody() = 0; + + // Sets up, executes, and tears down the test. + void Run(); + + // Deletes self. We deliberately pick an unusual name for this + // internal method to avoid clashing with names used in user TESTs. + void DeleteSelf_() { delete this; } + + // Uses a GTestFlagSaver to save and restore all Google Test flags. + const internal::GTestFlagSaver* const gtest_flag_saver_; + + // Often a user mis-spells SetUp() as Setup() and spends a long time + // wondering why it is never called by Google Test. The declaration of + // the following method is solely for catching such an error at + // compile time: + // + // - The return type is deliberately chosen to be not void, so it + // will be a conflict if a user declares void Setup() in his test + // fixture. + // + // - This method is private, so it will be another compiler error + // if a user calls it from his test fixture. + // + // DO NOT OVERRIDE THIS FUNCTION. + // + // If you see an error about overriding the following function or + // about it being private, you have mis-spelled SetUp() as Setup(). + struct Setup_should_be_spelled_SetUp {}; + virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; } + + // We disallow copying Tests. + GTEST_DISALLOW_COPY_AND_ASSIGN_(Test); +}; + +typedef internal::TimeInMillis TimeInMillis; + +// A copyable object representing a user specified test property which can be +// output as a key/value string pair. +// +// Don't inherit from TestProperty as its destructor is not virtual. +class TestProperty { + public: + // C'tor. TestProperty does NOT have a default constructor. + // Always use this constructor (with parameters) to create a + // TestProperty object. + TestProperty(const std::string& a_key, const std::string& a_value) : + key_(a_key), value_(a_value) { + } + + // Gets the user supplied key. + const char* key() const { + return key_.c_str(); + } + + // Gets the user supplied value. + const char* value() const { + return value_.c_str(); + } + + // Sets a new value, overriding the one supplied in the constructor. + void SetValue(const std::string& new_value) { + value_ = new_value; + } + + private: + // The key supplied by the user. + std::string key_; + // The value supplied by the user. + std::string value_; +}; + +// The result of a single Test. This includes a list of +// TestPartResults, a list of TestProperties, a count of how many +// death tests there are in the Test, and how much time it took to run +// the Test. +// +// TestResult is not copyable. +class GTEST_API_ TestResult { + public: + // Creates an empty TestResult. + TestResult(); + + // D'tor. Do not inherit from TestResult. + ~TestResult(); + + // Gets the number of all test parts. This is the sum of the number + // of successful test parts and the number of failed test parts. + int total_part_count() const; + + // Returns the number of the test properties. + int test_property_count() const; + + // Returns true iff the test passed (i.e. no test part failed). + bool Passed() const { return !Failed(); } + + // Returns true iff the test failed. + bool Failed() const; + + // Returns true iff the test fatally failed. + bool HasFatalFailure() const; + + // Returns true iff the test has a non-fatal failure. + bool HasNonfatalFailure() const; + + // Returns the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns the i-th test part result among all the results. i can range + // from 0 to test_property_count() - 1. If i is not in that range, aborts + // the program. + const TestPartResult& GetTestPartResult(int i) const; + + // Returns the i-th test property. i can range from 0 to + // test_property_count() - 1. If i is not in that range, aborts the + // program. + const TestProperty& GetTestProperty(int i) const; + + private: + friend class TestInfo; + friend class TestCase; + friend class UnitTest; + friend class internal::DefaultGlobalTestPartResultReporter; + friend class internal::ExecDeathTest; + friend class internal::TestResultAccessor; + friend class internal::UnitTestImpl; + friend class internal::WindowsDeathTest; + + // Gets the vector of TestPartResults. + const std::vector& test_part_results() const { + return test_part_results_; + } + + // Gets the vector of TestProperties. + const std::vector& test_properties() const { + return test_properties_; + } + + // Sets the elapsed time. + void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; } + + // Adds a test property to the list. The property is validated and may add + // a non-fatal failure if invalid (e.g., if it conflicts with reserved + // key names). If a property is already recorded for the same key, the + // value will be updated, rather than storing multiple values for the same + // key. xml_element specifies the element for which the property is being + // recorded and is used for validation. + void RecordProperty(const std::string& xml_element, + const TestProperty& test_property); + + // Adds a failure if the key is a reserved attribute of Google Test + // testcase tags. Returns true if the property is valid. + // TODO(russr): Validate attribute names are legal and human readable. + static bool ValidateTestProperty(const std::string& xml_element, + const TestProperty& test_property); + + // Adds a test part result to the list. + void AddTestPartResult(const TestPartResult& test_part_result); + + // Returns the death test count. + int death_test_count() const { return death_test_count_; } + + // Increments the death test count, returning the new count. + int increment_death_test_count() { return ++death_test_count_; } + + // Clears the test part results. + void ClearTestPartResults(); + + // Clears the object. + void Clear(); + + // Protects mutable state of the property vector and of owned + // properties, whose values may be updated. + internal::Mutex test_properites_mutex_; + + // The vector of TestPartResults + std::vector test_part_results_; + // The vector of TestProperties + std::vector test_properties_; + // Running count of death tests. + int death_test_count_; + // The elapsed time, in milliseconds. + TimeInMillis elapsed_time_; + + // We disallow copying TestResult. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestResult); +}; // class TestResult + +// A TestInfo object stores the following information about a test: +// +// Test case name +// Test name +// Whether the test should be run +// A function pointer that creates the test object when invoked +// Test result +// +// The constructor of TestInfo registers itself with the UnitTest +// singleton such that the RUN_ALL_TESTS() macro knows which tests to +// run. +class GTEST_API_ TestInfo { + public: + // Destructs a TestInfo object. This function is not virtual, so + // don't inherit from TestInfo. + ~TestInfo(); + + // Returns the test case name. + const char* test_case_name() const { return test_case_name_.c_str(); } + + // Returns the test name. + const char* name() const { return name_.c_str(); } + + // Returns the name of the parameter type, or NULL if this is not a typed + // or a type-parameterized test. + const char* type_param() const { + if (type_param_.get() != NULL) + return type_param_->c_str(); + return NULL; + } + + // Returns the text representation of the value parameter, or NULL if this + // is not a value-parameterized test. + const char* value_param() const { + if (value_param_.get() != NULL) + return value_param_->c_str(); + return NULL; + } + + // Returns true if this test should run, that is if the test is not + // disabled (or it is disabled but the also_run_disabled_tests flag has + // been specified) and its full name matches the user-specified filter. + // + // Google Test allows the user to filter the tests by their full names. + // The full name of a test Bar in test case Foo is defined as + // "Foo.Bar". Only the tests that match the filter will run. + // + // A filter is a colon-separated list of glob (not regex) patterns, + // optionally followed by a '-' and a colon-separated list of + // negative patterns (tests to exclude). A test is run if it + // matches one of the positive patterns and does not match any of + // the negative patterns. + // + // For example, *A*:Foo.* is a filter that matches any string that + // contains the character 'A' or starts with "Foo.". + bool should_run() const { return should_run_; } + + // Returns true iff this test will appear in the XML report. + bool is_reportable() const { + // For now, the XML report includes all tests matching the filter. + // In the future, we may trim tests that are excluded because of + // sharding. + return matches_filter_; + } + + // Returns the result of the test. + const TestResult* result() const { return &result_; } + + private: +#if GTEST_HAS_DEATH_TEST + friend class internal::DefaultDeathTestFactory; +#endif // GTEST_HAS_DEATH_TEST + friend class Test; + friend class TestCase; + friend class internal::UnitTestImpl; + friend class internal::StreamingListenerTest; + friend TestInfo* internal::MakeAndRegisterTestInfo( + const char* test_case_name, + const char* name, + const char* type_param, + const char* value_param, + internal::TypeId fixture_class_id, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc, + internal::TestFactoryBase* factory); + + // Constructs a TestInfo object. The newly constructed instance assumes + // ownership of the factory object. + TestInfo(const std::string& test_case_name, + const std::string& name, + const char* a_type_param, // NULL if not a type-parameterized test + const char* a_value_param, // NULL if not a value-parameterized test + internal::TypeId fixture_class_id, + internal::TestFactoryBase* factory); + + // Increments the number of death tests encountered in this test so + // far. + int increment_death_test_count() { + return result_.increment_death_test_count(); + } + + // Creates the test object, runs it, records its result, and then + // deletes it. + void Run(); + + static void ClearTestResult(TestInfo* test_info) { + test_info->result_.Clear(); + } + + // These fields are immutable properties of the test. + const std::string test_case_name_; // Test case name + const std::string name_; // Test name + // Name of the parameter type, or NULL if this is not a typed or a + // type-parameterized test. + const internal::scoped_ptr type_param_; + // Text representation of the value parameter, or NULL if this is not a + // value-parameterized test. + const internal::scoped_ptr value_param_; + const internal::TypeId fixture_class_id_; // ID of the test fixture class + bool should_run_; // True iff this test should run + bool is_disabled_; // True iff this test is disabled + bool matches_filter_; // True if this test matches the + // user-specified filter. + internal::TestFactoryBase* const factory_; // The factory that creates + // the test object + + // This field is mutable and needs to be reset before running the + // test for the second time. + TestResult result_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo); +}; + +// A test case, which consists of a vector of TestInfos. +// +// TestCase is not copyable. +class GTEST_API_ TestCase { + public: + // Creates a TestCase with the given name. + // + // TestCase does NOT have a default constructor. Always use this + // constructor to create a TestCase object. + // + // Arguments: + // + // name: name of the test case + // a_type_param: the name of the test's type parameter, or NULL if + // this is not a type-parameterized test. + // set_up_tc: pointer to the function that sets up the test case + // tear_down_tc: pointer to the function that tears down the test case + TestCase(const char* name, const char* a_type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc); + + // Destructor of TestCase. + virtual ~TestCase(); + + // Gets the name of the TestCase. + const char* name() const { return name_.c_str(); } + + // Returns the name of the parameter type, or NULL if this is not a + // type-parameterized test case. + const char* type_param() const { + if (type_param_.get() != NULL) + return type_param_->c_str(); + return NULL; + } + + // Returns true if any test in this test case should run. + bool should_run() const { return should_run_; } + + // Gets the number of successful tests in this test case. + int successful_test_count() const; + + // Gets the number of failed tests in this test case. + int failed_test_count() const; + + // Gets the number of disabled tests that will be reported in the XML report. + int reportable_disabled_test_count() const; + + // Gets the number of disabled tests in this test case. + int disabled_test_count() const; + + // Gets the number of tests to be printed in the XML report. + int reportable_test_count() const; + + // Get the number of tests in this test case that should run. + int test_to_run_count() const; + + // Gets the number of all tests in this test case. + int total_test_count() const; + + // Returns true iff the test case passed. + bool Passed() const { return !Failed(); } + + // Returns true iff the test case failed. + bool Failed() const { return failed_test_count() > 0; } + + // Returns the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns the i-th test among all the tests. i can range from 0 to + // total_test_count() - 1. If i is not in that range, returns NULL. + const TestInfo* GetTestInfo(int i) const; + + // Returns the TestResult that holds test properties recorded during + // execution of SetUpTestCase and TearDownTestCase. + const TestResult& ad_hoc_test_result() const { return ad_hoc_test_result_; } + + private: + friend class Test; + friend class internal::UnitTestImpl; + + // Gets the (mutable) vector of TestInfos in this TestCase. + std::vector& test_info_list() { return test_info_list_; } + + // Gets the (immutable) vector of TestInfos in this TestCase. + const std::vector& test_info_list() const { + return test_info_list_; + } + + // Returns the i-th test among all the tests. i can range from 0 to + // total_test_count() - 1. If i is not in that range, returns NULL. + TestInfo* GetMutableTestInfo(int i); + + // Sets the should_run member. + void set_should_run(bool should) { should_run_ = should; } + + // Adds a TestInfo to this test case. Will delete the TestInfo upon + // destruction of the TestCase object. + void AddTestInfo(TestInfo * test_info); + + // Clears the results of all tests in this test case. + void ClearResult(); + + // Clears the results of all tests in the given test case. + static void ClearTestCaseResult(TestCase* test_case) { + test_case->ClearResult(); + } + + // Runs every test in this TestCase. + void Run(); + + // Runs SetUpTestCase() for this TestCase. This wrapper is needed + // for catching exceptions thrown from SetUpTestCase(). + void RunSetUpTestCase() { (*set_up_tc_)(); } + + // Runs TearDownTestCase() for this TestCase. This wrapper is + // needed for catching exceptions thrown from TearDownTestCase(). + void RunTearDownTestCase() { (*tear_down_tc_)(); } + + // Returns true iff test passed. + static bool TestPassed(const TestInfo* test_info) { + return test_info->should_run() && test_info->result()->Passed(); + } + + // Returns true iff test failed. + static bool TestFailed(const TestInfo* test_info) { + return test_info->should_run() && test_info->result()->Failed(); + } + + // Returns true iff the test is disabled and will be reported in the XML + // report. + static bool TestReportableDisabled(const TestInfo* test_info) { + return test_info->is_reportable() && test_info->is_disabled_; + } + + // Returns true iff test is disabled. + static bool TestDisabled(const TestInfo* test_info) { + return test_info->is_disabled_; + } + + // Returns true iff this test will appear in the XML report. + static bool TestReportable(const TestInfo* test_info) { + return test_info->is_reportable(); + } + + // Returns true if the given test should run. + static bool ShouldRunTest(const TestInfo* test_info) { + return test_info->should_run(); + } + + // Shuffles the tests in this test case. + void ShuffleTests(internal::Random* random); + + // Restores the test order to before the first shuffle. + void UnshuffleTests(); + + // Name of the test case. + std::string name_; + // Name of the parameter type, or NULL if this is not a typed or a + // type-parameterized test. + const internal::scoped_ptr type_param_; + // The vector of TestInfos in their original order. It owns the + // elements in the vector. + std::vector test_info_list_; + // Provides a level of indirection for the test list to allow easy + // shuffling and restoring the test order. The i-th element in this + // vector is the index of the i-th test in the shuffled test list. + std::vector test_indices_; + // Pointer to the function that sets up the test case. + Test::SetUpTestCaseFunc set_up_tc_; + // Pointer to the function that tears down the test case. + Test::TearDownTestCaseFunc tear_down_tc_; + // True iff any test in this test case should run. + bool should_run_; + // Elapsed time, in milliseconds. + TimeInMillis elapsed_time_; + // Holds test properties recorded during execution of SetUpTestCase and + // TearDownTestCase. + TestResult ad_hoc_test_result_; + + // We disallow copying TestCases. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestCase); +}; + +// An Environment object is capable of setting up and tearing down an +// environment. The user should subclass this to define his own +// environment(s). +// +// An Environment object does the set-up and tear-down in virtual +// methods SetUp() and TearDown() instead of the constructor and the +// destructor, as: +// +// 1. You cannot safely throw from a destructor. This is a problem +// as in some cases Google Test is used where exceptions are enabled, and +// we may want to implement ASSERT_* using exceptions where they are +// available. +// 2. You cannot use ASSERT_* directly in a constructor or +// destructor. +class Environment { + public: + // The d'tor is virtual as we need to subclass Environment. + virtual ~Environment() {} + + // Override this to define how to set up the environment. + virtual void SetUp() {} + + // Override this to define how to tear down the environment. + virtual void TearDown() {} + private: + // If you see an error about overriding the following function or + // about it being private, you have mis-spelled SetUp() as Setup(). + struct Setup_should_be_spelled_SetUp {}; + virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; } +}; + +// The interface for tracing execution of tests. The methods are organized in +// the order the corresponding events are fired. +class TestEventListener { + public: + virtual ~TestEventListener() {} + + // Fired before any test activity starts. + virtual void OnTestProgramStart(const UnitTest& unit_test) = 0; + + // Fired before each iteration of tests starts. There may be more than + // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration + // index, starting from 0. + virtual void OnTestIterationStart(const UnitTest& unit_test, + int iteration) = 0; + + // Fired before environment set-up for each iteration of tests starts. + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0; + + // Fired after environment set-up for each iteration of tests ends. + virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0; + + // Fired before the test case starts. + virtual void OnTestCaseStart(const TestCase& test_case) = 0; + + // Fired before the test starts. + virtual void OnTestStart(const TestInfo& test_info) = 0; + + // Fired after a failed assertion or a SUCCEED() invocation. + virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0; + + // Fired after the test ends. + virtual void OnTestEnd(const TestInfo& test_info) = 0; + + // Fired after the test case ends. + virtual void OnTestCaseEnd(const TestCase& test_case) = 0; + + // Fired before environment tear-down for each iteration of tests starts. + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0; + + // Fired after environment tear-down for each iteration of tests ends. + virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0; + + // Fired after each iteration of tests finishes. + virtual void OnTestIterationEnd(const UnitTest& unit_test, + int iteration) = 0; + + // Fired after all test activities have ended. + virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0; +}; + +// The convenience class for users who need to override just one or two +// methods and are not concerned that a possible change to a signature of +// the methods they override will not be caught during the build. For +// comments about each method please see the definition of TestEventListener +// above. +class EmptyTestEventListener : public TestEventListener { + public: + virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationStart(const UnitTest& /*unit_test*/, + int /*iteration*/) {} + virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {} + virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestCaseStart(const TestCase& /*test_case*/) {} + virtual void OnTestStart(const TestInfo& /*test_info*/) {} + virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {} + virtual void OnTestEnd(const TestInfo& /*test_info*/) {} + virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {} + virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {} + virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/, + int /*iteration*/) {} + virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} +}; + +// TestEventListeners lets users add listeners to track events in Google Test. +class GTEST_API_ TestEventListeners { + public: + TestEventListeners(); + ~TestEventListeners(); + + // Appends an event listener to the end of the list. Google Test assumes + // the ownership of the listener (i.e. it will delete the listener when + // the test program finishes). + void Append(TestEventListener* listener); + + // Removes the given event listener from the list and returns it. It then + // becomes the caller's responsibility to delete the listener. Returns + // NULL if the listener is not found in the list. + TestEventListener* Release(TestEventListener* listener); + + // Returns the standard listener responsible for the default console + // output. Can be removed from the listeners list to shut down default + // console output. Note that removing this object from the listener list + // with Release transfers its ownership to the caller and makes this + // function return NULL the next time. + TestEventListener* default_result_printer() const { + return default_result_printer_; + } + + // Returns the standard listener responsible for the default XML output + // controlled by the --gtest_output=xml flag. Can be removed from the + // listeners list by users who want to shut down the default XML output + // controlled by this flag and substitute it with custom one. Note that + // removing this object from the listener list with Release transfers its + // ownership to the caller and makes this function return NULL the next + // time. + TestEventListener* default_xml_generator() const { + return default_xml_generator_; + } + + private: + friend class TestCase; + friend class TestInfo; + friend class internal::DefaultGlobalTestPartResultReporter; + friend class internal::NoExecDeathTest; + friend class internal::TestEventListenersAccessor; + friend class internal::UnitTestImpl; + + // Returns repeater that broadcasts the TestEventListener events to all + // subscribers. + TestEventListener* repeater(); + + // Sets the default_result_printer attribute to the provided listener. + // The listener is also added to the listener list and previous + // default_result_printer is removed from it and deleted. The listener can + // also be NULL in which case it will not be added to the list. Does + // nothing if the previous and the current listener objects are the same. + void SetDefaultResultPrinter(TestEventListener* listener); + + // Sets the default_xml_generator attribute to the provided listener. The + // listener is also added to the listener list and previous + // default_xml_generator is removed from it and deleted. The listener can + // also be NULL in which case it will not be added to the list. Does + // nothing if the previous and the current listener objects are the same. + void SetDefaultXmlGenerator(TestEventListener* listener); + + // Controls whether events will be forwarded by the repeater to the + // listeners in the list. + bool EventForwardingEnabled() const; + void SuppressEventForwarding(); + + // The actual list of listeners. + internal::TestEventRepeater* repeater_; + // Listener responsible for the standard result output. + TestEventListener* default_result_printer_; + // Listener responsible for the creation of the XML output file. + TestEventListener* default_xml_generator_; + + // We disallow copying TestEventListeners. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventListeners); +}; + +// A UnitTest consists of a vector of TestCases. +// +// This is a singleton class. The only instance of UnitTest is +// created when UnitTest::GetInstance() is first called. This +// instance is never deleted. +// +// UnitTest is not copyable. +// +// This class is thread-safe as long as the methods are called +// according to their specification. +class GTEST_API_ UnitTest { + public: + // Gets the singleton UnitTest object. The first time this method + // is called, a UnitTest object is constructed and returned. + // Consecutive calls will return the same object. + static UnitTest* GetInstance(); + + // Runs all tests in this UnitTest object and prints the result. + // Returns 0 if successful, or 1 otherwise. + // + // This method can only be called from the main thread. + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + int Run() GTEST_MUST_USE_RESULT_; + + // Returns the working directory when the first TEST() or TEST_F() + // was executed. The UnitTest object owns the string. + const char* original_working_dir() const; + + // Returns the TestCase object for the test that's currently running, + // or NULL if no test is running. + const TestCase* current_test_case() const + GTEST_LOCK_EXCLUDED_(mutex_); + + // Returns the TestInfo object for the test that's currently running, + // or NULL if no test is running. + const TestInfo* current_test_info() const + GTEST_LOCK_EXCLUDED_(mutex_); + + // Returns the random seed used at the start of the current test run. + int random_seed() const; + +#if GTEST_HAS_PARAM_TEST + // Returns the ParameterizedTestCaseRegistry object used to keep track of + // value-parameterized tests and instantiate and register them. + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + internal::ParameterizedTestCaseRegistry& parameterized_test_registry() + GTEST_LOCK_EXCLUDED_(mutex_); +#endif // GTEST_HAS_PARAM_TEST + + // Gets the number of successful test cases. + int successful_test_case_count() const; + + // Gets the number of failed test cases. + int failed_test_case_count() const; + + // Gets the number of all test cases. + int total_test_case_count() const; + + // Gets the number of all test cases that contain at least one test + // that should run. + int test_case_to_run_count() const; + + // Gets the number of successful tests. + int successful_test_count() const; + + // Gets the number of failed tests. + int failed_test_count() const; + + // Gets the number of disabled tests that will be reported in the XML report. + int reportable_disabled_test_count() const; + + // Gets the number of disabled tests. + int disabled_test_count() const; + + // Gets the number of tests to be printed in the XML report. + int reportable_test_count() const; + + // Gets the number of all tests. + int total_test_count() const; + + // Gets the number of tests that should run. + int test_to_run_count() const; + + // Gets the time of the test program start, in ms from the start of the + // UNIX epoch. + TimeInMillis start_timestamp() const; + + // Gets the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const; + + // Returns true iff the unit test passed (i.e. all test cases passed). + bool Passed() const; + + // Returns true iff the unit test failed (i.e. some test case failed + // or something outside of all tests failed). + bool Failed() const; + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + const TestCase* GetTestCase(int i) const; + + // Returns the TestResult containing information on test failures and + // properties logged outside of individual test cases. + const TestResult& ad_hoc_test_result() const; + + // Returns the list of event listeners that can be used to track events + // inside Google Test. + TestEventListeners& listeners(); + + private: + // Registers and returns a global test environment. When a test + // program is run, all global test environments will be set-up in + // the order they were registered. After all tests in the program + // have finished, all global test environments will be torn-down in + // the *reverse* order they were registered. + // + // The UnitTest object takes ownership of the given environment. + // + // This method can only be called from the main thread. + Environment* AddEnvironment(Environment* env); + + // Adds a TestPartResult to the current TestResult object. All + // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) + // eventually call this to report their results. The user code + // should use the assertion macros instead of calling this directly. + void AddTestPartResult(TestPartResult::Type result_type, + const char* file_name, + int line_number, + const std::string& message, + const std::string& os_stack_trace) + GTEST_LOCK_EXCLUDED_(mutex_); + + // Adds a TestProperty to the current TestResult object when invoked from + // inside a test, to current TestCase's ad_hoc_test_result_ when invoked + // from SetUpTestCase or TearDownTestCase, or to the global property set + // when invoked elsewhere. If the result already contains a property with + // the same key, the value will be updated. + void RecordProperty(const std::string& key, const std::string& value); + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + TestCase* GetMutableTestCase(int i); + + // Accessors for the implementation object. + internal::UnitTestImpl* impl() { return impl_; } + const internal::UnitTestImpl* impl() const { return impl_; } + + // These classes and funcions are friends as they need to access private + // members of UnitTest. + friend class Test; + friend class internal::AssertHelper; + friend class internal::ScopedTrace; + friend class internal::StreamingListenerTest; + friend class internal::UnitTestRecordPropertyTestHelper; + friend Environment* AddGlobalTestEnvironment(Environment* env); + friend internal::UnitTestImpl* internal::GetUnitTestImpl(); + friend void internal::ReportFailureInUnknownLocation( + TestPartResult::Type result_type, + const std::string& message); + + // Creates an empty UnitTest. + UnitTest(); + + // D'tor + virtual ~UnitTest(); + + // Pushes a trace defined by SCOPED_TRACE() on to the per-thread + // Google Test trace stack. + void PushGTestTrace(const internal::TraceInfo& trace) + GTEST_LOCK_EXCLUDED_(mutex_); + + // Pops a trace from the per-thread Google Test trace stack. + void PopGTestTrace() + GTEST_LOCK_EXCLUDED_(mutex_); + + // Protects mutable state in *impl_. This is mutable as some const + // methods need to lock it too. + mutable internal::Mutex mutex_; + + // Opaque implementation object. This field is never changed once + // the object is constructed. We don't mark it as const here, as + // doing so will cause a warning in the constructor of UnitTest. + // Mutable state in *impl_ is protected by mutex_. + internal::UnitTestImpl* impl_; + + // We disallow copying UnitTest. + GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTest); +}; + +// A convenient wrapper for adding an environment for the test +// program. +// +// You should call this before RUN_ALL_TESTS() is called, probably in +// main(). If you use gtest_main, you need to call this before main() +// starts for it to take effect. For example, you can define a global +// variable like this: +// +// testing::Environment* const foo_env = +// testing::AddGlobalTestEnvironment(new FooEnvironment); +// +// However, we strongly recommend you to write your own main() and +// call AddGlobalTestEnvironment() there, as relying on initialization +// of global variables makes the code harder to read and may cause +// problems when you register multiple environments from different +// translation units and the environments have dependencies among them +// (remember that the compiler doesn't guarantee the order in which +// global variables from different translation units are initialized). +inline Environment* AddGlobalTestEnvironment(Environment* env) { + return UnitTest::GetInstance()->AddEnvironment(env); +} + +// Initializes Google Test. This must be called before calling +// RUN_ALL_TESTS(). In particular, it parses a command line for the +// flags that Google Test recognizes. Whenever a Google Test flag is +// seen, it is removed from argv, and *argc is decremented. +// +// No value is returned. Instead, the Google Test flag variables are +// updated. +// +// Calling the function for the second time has no user-visible effect. +GTEST_API_ void InitGoogleTest(int* argc, char** argv); + +// This overloaded version can be used in Windows programs compiled in +// UNICODE mode. +GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv); + +namespace internal { + +// FormatForComparison::Format(value) formats a +// value of type ToPrint that is an operand of a comparison assertion +// (e.g. ASSERT_EQ). OtherOperand is the type of the other operand in +// the comparison, and is used to help determine the best way to +// format the value. In particular, when the value is a C string +// (char pointer) and the other operand is an STL string object, we +// want to format the C string as a string, since we know it is +// compared by value with the string object. If the value is a char +// pointer but the other operand is not an STL string object, we don't +// know whether the pointer is supposed to point to a NUL-terminated +// string, and thus want to print it as a pointer to be safe. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + +// The default case. +template +class FormatForComparison { + public: + static ::std::string Format(const ToPrint& value) { + return ::testing::PrintToString(value); + } +}; + +// Array. +template +class FormatForComparison { + public: + static ::std::string Format(const ToPrint* value) { + return FormatForComparison::Format(value); + } +}; + +// By default, print C string as pointers to be safe, as we don't know +// whether they actually point to a NUL-terminated string. + +#define GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(CharType) \ + template \ + class FormatForComparison { \ + public: \ + static ::std::string Format(CharType* value) { \ + return ::testing::PrintToString(static_cast(value)); \ + } \ + } + +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t); + +#undef GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_ + +// If a C string is compared with an STL string object, we know it's meant +// to point to a NUL-terminated string, and thus can print it as a string. + +#define GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(CharType, OtherStringType) \ + template <> \ + class FormatForComparison { \ + public: \ + static ::std::string Format(CharType* value) { \ + return ::testing::PrintToString(value); \ + } \ + } + +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string); + +#if GTEST_HAS_GLOBAL_STRING +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::string); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::string); +#endif + +#if GTEST_HAS_GLOBAL_WSTRING +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::wstring); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::wstring); +#endif + +#if GTEST_HAS_STD_WSTRING +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring); +#endif + +#undef GTEST_IMPL_FORMAT_C_STRING_AS_STRING_ + +// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc) +// operand to be used in a failure message. The type (but not value) +// of the other operand may affect the format. This allows us to +// print a char* as a raw pointer when it is compared against another +// char* or void*, and print it as a C string when it is compared +// against an std::string object, for example. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +template +std::string FormatForComparisonFailureMessage( + const T1& value, const T2& /* other_operand */) { + return FormatForComparison::Format(value); +} + +// The helper function for {ASSERT|EXPECT}_EQ. +template +AssertionResult CmpHelperEQ(const char* expected_expression, + const char* actual_expression, + const T1& expected, + const T2& actual) { +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4389) // Temporarily disables warning on + // signed/unsigned mismatch. +#endif + + if (expected == actual) { + return AssertionSuccess(); + } + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif + + return EqFailure(expected_expression, + actual_expression, + FormatForComparisonFailureMessage(expected, actual), + FormatForComparisonFailureMessage(actual, expected), + false); +} + +// With this overloaded version, we allow anonymous enums to be used +// in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums +// can be implicitly cast to BiggestInt. +GTEST_API_ AssertionResult CmpHelperEQ(const char* expected_expression, + const char* actual_expression, + BiggestInt expected, + BiggestInt actual); + +// The helper class for {ASSERT|EXPECT}_EQ. The template argument +// lhs_is_null_literal is true iff the first argument to ASSERT_EQ() +// is a null pointer literal. The following default implementation is +// for lhs_is_null_literal being false. +template +class EqHelper { + public: + // This templatized version is for the general case. + template + static AssertionResult Compare(const char* expected_expression, + const char* actual_expression, + const T1& expected, + const T2& actual) { + return CmpHelperEQ(expected_expression, actual_expression, expected, + actual); + } + + // With this overloaded version, we allow anonymous enums to be used + // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous + // enums can be implicitly cast to BiggestInt. + // + // Even though its body looks the same as the above version, we + // cannot merge the two, as it will make anonymous enums unhappy. + static AssertionResult Compare(const char* expected_expression, + const char* actual_expression, + BiggestInt expected, + BiggestInt actual) { + return CmpHelperEQ(expected_expression, actual_expression, expected, + actual); + } +}; + +// This specialization is used when the first argument to ASSERT_EQ() +// is a null pointer literal, like NULL, false, or 0. +template <> +class EqHelper { + public: + // We define two overloaded versions of Compare(). The first + // version will be picked when the second argument to ASSERT_EQ() is + // NOT a pointer, e.g. ASSERT_EQ(0, AnIntFunction()) or + // EXPECT_EQ(false, a_bool). + template + static AssertionResult Compare( + const char* expected_expression, + const char* actual_expression, + const T1& expected, + const T2& actual, + // The following line prevents this overload from being considered if T2 + // is not a pointer type. We need this because ASSERT_EQ(NULL, my_ptr) + // expands to Compare("", "", NULL, my_ptr), which requires a conversion + // to match the Secret* in the other overload, which would otherwise make + // this template match better. + typename EnableIf::value>::type* = 0) { + return CmpHelperEQ(expected_expression, actual_expression, expected, + actual); + } + + // This version will be picked when the second argument to ASSERT_EQ() is a + // pointer, e.g. ASSERT_EQ(NULL, a_pointer). + template + static AssertionResult Compare( + const char* expected_expression, + const char* actual_expression, + // We used to have a second template parameter instead of Secret*. That + // template parameter would deduce to 'long', making this a better match + // than the first overload even without the first overload's EnableIf. + // Unfortunately, gcc with -Wconversion-null warns when "passing NULL to + // non-pointer argument" (even a deduced integral argument), so the old + // implementation caused warnings in user code. + Secret* /* expected (NULL) */, + T* actual) { + // We already know that 'expected' is a null pointer. + return CmpHelperEQ(expected_expression, actual_expression, + static_cast(NULL), actual); + } +}; + +// A macro for implementing the helper functions needed to implement +// ASSERT_?? and EXPECT_??. It is here just to avoid copy-and-paste +// of similar code. +// +// For each templatized helper function, we also define an overloaded +// version for BiggestInt in order to reduce code bloat and allow +// anonymous enums to be used with {ASSERT|EXPECT}_?? when compiled +// with gcc 4. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +#define GTEST_IMPL_CMP_HELPER_(op_name, op)\ +template \ +AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ + const T1& val1, const T2& val2) {\ + if (val1 op val2) {\ + return AssertionSuccess();\ + } else {\ + return AssertionFailure() \ + << "Expected: (" << expr1 << ") " #op " (" << expr2\ + << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\ + << " vs " << FormatForComparisonFailureMessage(val2, val1);\ + }\ +}\ +GTEST_API_ AssertionResult CmpHelper##op_name(\ + const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2) + +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + +// Implements the helper function for {ASSERT|EXPECT}_NE +GTEST_IMPL_CMP_HELPER_(NE, !=); +// Implements the helper function for {ASSERT|EXPECT}_LE +GTEST_IMPL_CMP_HELPER_(LE, <=); +// Implements the helper function for {ASSERT|EXPECT}_LT +GTEST_IMPL_CMP_HELPER_(LT, <); +// Implements the helper function for {ASSERT|EXPECT}_GE +GTEST_IMPL_CMP_HELPER_(GE, >=); +// Implements the helper function for {ASSERT|EXPECT}_GT +GTEST_IMPL_CMP_HELPER_(GT, >); + +#undef GTEST_IMPL_CMP_HELPER_ + +// The helper function for {ASSERT|EXPECT}_STREQ. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual); + +// The helper function for {ASSERT|EXPECT}_STRCASEEQ. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual); + +// The helper function for {ASSERT|EXPECT}_STRNE. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2); + +// The helper function for {ASSERT|EXPECT}_STRCASENE. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2); + + +// Helper function for *_STREQ on wide strings. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const wchar_t* expected, + const wchar_t* actual); + +// Helper function for *_STRNE on wide strings. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const wchar_t* s1, + const wchar_t* s2); + +} // namespace internal + +// IsSubstring() and IsNotSubstring() are intended to be used as the +// first argument to {EXPECT,ASSERT}_PRED_FORMAT2(), not by +// themselves. They check whether needle is a substring of haystack +// (NULL is considered a substring of itself only), and return an +// appropriate error message when they fail. +// +// The {needle,haystack}_expr arguments are the stringified +// expressions that generated the two real arguments. +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack); +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack); +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack); + +#if GTEST_HAS_STD_WSTRING +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack); +#endif // GTEST_HAS_STD_WSTRING + +namespace internal { + +// Helper template function for comparing floating-points. +// +// Template parameter: +// +// RawType: the raw floating-point type (either float or double) +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +template +AssertionResult CmpHelperFloatingPointEQ(const char* expected_expression, + const char* actual_expression, + RawType expected, + RawType actual) { + const FloatingPoint lhs(expected), rhs(actual); + + if (lhs.AlmostEquals(rhs)) { + return AssertionSuccess(); + } + + ::std::stringstream expected_ss; + expected_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << expected; + + ::std::stringstream actual_ss; + actual_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << actual; + + return EqFailure(expected_expression, + actual_expression, + StringStreamToString(&expected_ss), + StringStreamToString(&actual_ss), + false); +} + +// Helper function for implementing ASSERT_NEAR. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1, + const char* expr2, + const char* abs_error_expr, + double val1, + double val2, + double abs_error); + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// A class that enables one to stream messages to assertion macros +class GTEST_API_ AssertHelper { + public: + // Constructor. + AssertHelper(TestPartResult::Type type, + const char* file, + int line, + const char* message); + ~AssertHelper(); + + // Message assignment is a semantic trick to enable assertion + // streaming; see the GTEST_MESSAGE_ macro below. + void operator=(const Message& message) const; + + private: + // We put our data in a struct so that the size of the AssertHelper class can + // be as small as possible. This is important because gcc is incapable of + // re-using stack space even for temporary variables, so every EXPECT_EQ + // reserves stack space for another AssertHelper. + struct AssertHelperData { + AssertHelperData(TestPartResult::Type t, + const char* srcfile, + int line_num, + const char* msg) + : type(t), file(srcfile), line(line_num), message(msg) { } + + TestPartResult::Type const type; + const char* const file; + int const line; + std::string const message; + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData); + }; + + AssertHelperData* const data_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper); +}; + +} // namespace internal + +#if GTEST_HAS_PARAM_TEST +// The pure interface class that all value-parameterized tests inherit from. +// A value-parameterized class must inherit from both ::testing::Test and +// ::testing::WithParamInterface. In most cases that just means inheriting +// from ::testing::TestWithParam, but more complicated test hierarchies +// may need to inherit from Test and WithParamInterface at different levels. +// +// This interface has support for accessing the test parameter value via +// the GetParam() method. +// +// Use it with one of the parameter generator defining functions, like Range(), +// Values(), ValuesIn(), Bool(), and Combine(). +// +// class FooTest : public ::testing::TestWithParam { +// protected: +// FooTest() { +// // Can use GetParam() here. +// } +// virtual ~FooTest() { +// // Can use GetParam() here. +// } +// virtual void SetUp() { +// // Can use GetParam() here. +// } +// virtual void TearDown { +// // Can use GetParam() here. +// } +// }; +// TEST_P(FooTest, DoesBar) { +// // Can use GetParam() method here. +// Foo foo; +// ASSERT_TRUE(foo.DoesBar(GetParam())); +// } +// INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10)); + +template +class WithParamInterface { + public: + typedef T ParamType; + virtual ~WithParamInterface() {} + + // The current parameter value. Is also available in the test fixture's + // constructor. This member function is non-static, even though it only + // references static data, to reduce the opportunity for incorrect uses + // like writing 'WithParamInterface::GetParam()' for a test that + // uses a fixture whose parameter type is int. + const ParamType& GetParam() const { + GTEST_CHECK_(parameter_ != NULL) + << "GetParam() can only be called inside a value-parameterized test " + << "-- did you intend to write TEST_P instead of TEST_F?"; + return *parameter_; + } + + private: + // Sets parameter value. The caller is responsible for making sure the value + // remains alive and unchanged throughout the current test. + static void SetParam(const ParamType* parameter) { + parameter_ = parameter; + } + + // Static value used for accessing parameter during a test lifetime. + static const ParamType* parameter_; + + // TestClass must be a subclass of WithParamInterface and Test. + template friend class internal::ParameterizedTestFactory; +}; + +template +const T* WithParamInterface::parameter_ = NULL; + +// Most value-parameterized classes can ignore the existence of +// WithParamInterface, and can just inherit from ::testing::TestWithParam. + +template +class TestWithParam : public Test, public WithParamInterface { +}; + +#endif // GTEST_HAS_PARAM_TEST + +// Macros for indicating success/failure in test code. + +// ADD_FAILURE unconditionally adds a failure to the current test. +// SUCCEED generates a success - it doesn't automatically make the +// current test successful, as a test is only successful when it has +// no failure. +// +// EXPECT_* verifies that a certain condition is satisfied. If not, +// it behaves like ADD_FAILURE. In particular: +// +// EXPECT_TRUE verifies that a Boolean condition is true. +// EXPECT_FALSE verifies that a Boolean condition is false. +// +// FAIL and ASSERT_* are similar to ADD_FAILURE and EXPECT_*, except +// that they will also abort the current function on failure. People +// usually want the fail-fast behavior of FAIL and ASSERT_*, but those +// writing data-driven tests often find themselves using ADD_FAILURE +// and EXPECT_* more. + +// Generates a nonfatal failure with a generic message. +#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed") + +// Generates a nonfatal failure at the given source file location with +// a generic message. +#define ADD_FAILURE_AT(file, line) \ + GTEST_MESSAGE_AT_(file, line, "Failed", \ + ::testing::TestPartResult::kNonFatalFailure) + +// Generates a fatal failure with a generic message. +#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed") + +// Define this macro to 1 to omit the definition of FAIL(), which is a +// generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_FAIL +# define FAIL() GTEST_FAIL() +#endif + +// Generates a success with a generic message. +#define GTEST_SUCCEED() GTEST_SUCCESS_("Succeeded") + +// Define this macro to 1 to omit the definition of SUCCEED(), which +// is a generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_SUCCEED +# define SUCCEED() GTEST_SUCCEED() +#endif + +// Macros for testing exceptions. +// +// * {ASSERT|EXPECT}_THROW(statement, expected_exception): +// Tests that the statement throws the expected exception. +// * {ASSERT|EXPECT}_NO_THROW(statement): +// Tests that the statement doesn't throw any exception. +// * {ASSERT|EXPECT}_ANY_THROW(statement): +// Tests that the statement throws an exception. + +#define EXPECT_THROW(statement, expected_exception) \ + GTEST_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_) +#define EXPECT_NO_THROW(statement) \ + GTEST_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_) +#define EXPECT_ANY_THROW(statement) \ + GTEST_TEST_ANY_THROW_(statement, GTEST_NONFATAL_FAILURE_) +#define ASSERT_THROW(statement, expected_exception) \ + GTEST_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_) +#define ASSERT_NO_THROW(statement) \ + GTEST_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_) +#define ASSERT_ANY_THROW(statement) \ + GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_) + +// Boolean assertions. Condition can be either a Boolean expression or an +// AssertionResult. For more information on how to use AssertionResult with +// these macros see comments on that class. +#define EXPECT_TRUE(condition) \ + GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ + GTEST_NONFATAL_FAILURE_) +#define EXPECT_FALSE(condition) \ + GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ + GTEST_NONFATAL_FAILURE_) +#define ASSERT_TRUE(condition) \ + GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ + GTEST_FATAL_FAILURE_) +#define ASSERT_FALSE(condition) \ + GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ + GTEST_FATAL_FAILURE_) + +// Includes the auto-generated header that implements a family of +// generic predicate assertion macros. +// Copyright 2006, 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. + +// This file is AUTOMATICALLY GENERATED on 10/31/2011 by command +// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND! +// +// Implements a family of generic predicate assertion macros. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ + +// Makes sure this header is not included before gtest.h. +#ifndef GTEST_INCLUDE_GTEST_GTEST_H_ +# error Do not include gtest_pred_impl.h directly. Include gtest.h instead. +#endif // GTEST_INCLUDE_GTEST_GTEST_H_ + +// This header implements a family of generic predicate assertion +// macros: +// +// ASSERT_PRED_FORMAT1(pred_format, v1) +// ASSERT_PRED_FORMAT2(pred_format, v1, v2) +// ... +// +// where pred_format is a function or functor that takes n (in the +// case of ASSERT_PRED_FORMATn) values and their source expression +// text, and returns a testing::AssertionResult. See the definition +// of ASSERT_EQ in gtest.h for an example. +// +// If you don't care about formatting, you can use the more +// restrictive version: +// +// ASSERT_PRED1(pred, v1) +// ASSERT_PRED2(pred, v1, v2) +// ... +// +// where pred is an n-ary function or functor that returns bool, +// and the values v1, v2, ..., must support the << operator for +// streaming to std::ostream. +// +// We also define the EXPECT_* variations. +// +// For now we only support predicates whose arity is at most 5. +// Please email googletestframework@googlegroups.com if you need +// support for higher arities. + +// GTEST_ASSERT_ is the basic statement to which all of the assertions +// in this file reduce. Don't use this in your code. + +#define GTEST_ASSERT_(expression, on_failure) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (const ::testing::AssertionResult gtest_ar = (expression)) \ + ; \ + else \ + on_failure(gtest_ar.failure_message()) + + +// Helper function for implementing {EXPECT|ASSERT}_PRED1. Don't use +// this in your code. +template +AssertionResult AssertPred1Helper(const char* pred_text, + const char* e1, + Pred pred, + const T1& v1) { + if (pred(v1)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1. +// Don't use this in your code. +#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, v1), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED1. Don't use +// this in your code. +#define GTEST_PRED1_(pred, v1, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \ + #v1, \ + pred, \ + v1), on_failure) + +// Unary predicate assertion macros. +#define EXPECT_PRED_FORMAT1(pred_format, v1) \ + GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED1(pred, v1) \ + GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT1(pred_format, v1) \ + GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED1(pred, v1) \ + GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED2. Don't use +// this in your code. +template +AssertionResult AssertPred2Helper(const char* pred_text, + const char* e1, + const char* e2, + Pred pred, + const T1& v1, + const T2& v2) { + if (pred(v1, v2)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2. +// Don't use this in your code. +#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED2. Don't use +// this in your code. +#define GTEST_PRED2_(pred, v1, v2, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \ + #v1, \ + #v2, \ + pred, \ + v1, \ + v2), on_failure) + +// Binary predicate assertion macros. +#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \ + GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED2(pred, v1, v2) \ + GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \ + GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED2(pred, v1, v2) \ + GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED3. Don't use +// this in your code. +template +AssertionResult AssertPred3Helper(const char* pred_text, + const char* e1, + const char* e2, + const char* e3, + Pred pred, + const T1& v1, + const T2& v2, + const T3& v3) { + if (pred(v1, v2, v3)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ", " + << e3 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2 + << "\n" << e3 << " evaluates to " << v3; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3. +// Don't use this in your code. +#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED3. Don't use +// this in your code. +#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \ + #v1, \ + #v2, \ + #v3, \ + pred, \ + v1, \ + v2, \ + v3), on_failure) + +// Ternary predicate assertion macros. +#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \ + GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED3(pred, v1, v2, v3) \ + GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \ + GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED3(pred, v1, v2, v3) \ + GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED4. Don't use +// this in your code. +template +AssertionResult AssertPred4Helper(const char* pred_text, + const char* e1, + const char* e2, + const char* e3, + const char* e4, + Pred pred, + const T1& v1, + const T2& v2, + const T3& v3, + const T4& v4) { + if (pred(v1, v2, v3, v4)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ", " + << e3 << ", " + << e4 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2 + << "\n" << e3 << " evaluates to " << v3 + << "\n" << e4 << " evaluates to " << v4; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4. +// Don't use this in your code. +#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED4. Don't use +// this in your code. +#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \ + #v1, \ + #v2, \ + #v3, \ + #v4, \ + pred, \ + v1, \ + v2, \ + v3, \ + v4), on_failure) + +// 4-ary predicate assertion macros. +#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \ + GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED4(pred, v1, v2, v3, v4) \ + GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \ + GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED4(pred, v1, v2, v3, v4) \ + GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED5. Don't use +// this in your code. +template +AssertionResult AssertPred5Helper(const char* pred_text, + const char* e1, + const char* e2, + const char* e3, + const char* e4, + const char* e5, + Pred pred, + const T1& v1, + const T2& v2, + const T3& v3, + const T4& v4, + const T5& v5) { + if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ", " + << e3 << ", " + << e4 << ", " + << e5 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2 + << "\n" << e3 << " evaluates to " << v3 + << "\n" << e4 << " evaluates to " << v4 + << "\n" << e5 << " evaluates to " << v5; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5. +// Don't use this in your code. +#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED5. Don't use +// this in your code. +#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \ + #v1, \ + #v2, \ + #v3, \ + #v4, \ + #v5, \ + pred, \ + v1, \ + v2, \ + v3, \ + v4, \ + v5), on_failure) + +// 5-ary predicate assertion macros. +#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \ + GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \ + GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \ + GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \ + GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_) + + + +#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ + +// Macros for testing equalities and inequalities. +// +// * {ASSERT|EXPECT}_EQ(expected, actual): Tests that expected == actual +// * {ASSERT|EXPECT}_NE(v1, v2): Tests that v1 != v2 +// * {ASSERT|EXPECT}_LT(v1, v2): Tests that v1 < v2 +// * {ASSERT|EXPECT}_LE(v1, v2): Tests that v1 <= v2 +// * {ASSERT|EXPECT}_GT(v1, v2): Tests that v1 > v2 +// * {ASSERT|EXPECT}_GE(v1, v2): Tests that v1 >= v2 +// +// When they are not, Google Test prints both the tested expressions and +// their actual values. The values must be compatible built-in types, +// or you will get a compiler error. By "compatible" we mean that the +// values can be compared by the respective operator. +// +// Note: +// +// 1. It is possible to make a user-defined type work with +// {ASSERT|EXPECT}_??(), but that requires overloading the +// comparison operators and is thus discouraged by the Google C++ +// Usage Guide. Therefore, you are advised to use the +// {ASSERT|EXPECT}_TRUE() macro to assert that two objects are +// equal. +// +// 2. The {ASSERT|EXPECT}_??() macros do pointer comparisons on +// pointers (in particular, C strings). Therefore, if you use it +// with two C strings, you are testing how their locations in memory +// are related, not how their content is related. To compare two C +// strings by content, use {ASSERT|EXPECT}_STR*(). +// +// 3. {ASSERT|EXPECT}_EQ(expected, actual) is preferred to +// {ASSERT|EXPECT}_TRUE(expected == actual), as the former tells you +// what the actual value is when it fails, and similarly for the +// other comparisons. +// +// 4. Do not depend on the order in which {ASSERT|EXPECT}_??() +// evaluate their arguments, which is undefined. +// +// 5. These macros evaluate their arguments exactly once. +// +// Examples: +// +// EXPECT_NE(5, Foo()); +// EXPECT_EQ(NULL, a_pointer); +// ASSERT_LT(i, array_size); +// ASSERT_GT(records.size(), 0) << "There is no record left."; + +#define EXPECT_EQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal:: \ + EqHelper::Compare, \ + expected, actual) +#define EXPECT_NE(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, expected, actual) +#define EXPECT_LE(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2) +#define EXPECT_LT(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2) +#define EXPECT_GE(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2) +#define EXPECT_GT(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2) + +#define GTEST_ASSERT_EQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::testing::internal:: \ + EqHelper::Compare, \ + expected, actual) +#define GTEST_ASSERT_NE(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2) +#define GTEST_ASSERT_LE(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2) +#define GTEST_ASSERT_LT(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2) +#define GTEST_ASSERT_GE(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2) +#define GTEST_ASSERT_GT(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2) + +// Define macro GTEST_DONT_DEFINE_ASSERT_XY to 1 to omit the definition of +// ASSERT_XY(), which clashes with some users' own code. + +#if !GTEST_DONT_DEFINE_ASSERT_EQ +# define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_NE +# define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_LE +# define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_LT +# define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_GE +# define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_GT +# define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2) +#endif + +// C-string Comparisons. All tests treat NULL and any non-NULL string +// as different. Two NULLs are equal. +// +// * {ASSERT|EXPECT}_STREQ(s1, s2): Tests that s1 == s2 +// * {ASSERT|EXPECT}_STRNE(s1, s2): Tests that s1 != s2 +// * {ASSERT|EXPECT}_STRCASEEQ(s1, s2): Tests that s1 == s2, ignoring case +// * {ASSERT|EXPECT}_STRCASENE(s1, s2): Tests that s1 != s2, ignoring case +// +// For wide or narrow string objects, you can use the +// {ASSERT|EXPECT}_??() macros. +// +// Don't depend on the order in which the arguments are evaluated, +// which is undefined. +// +// These macros evaluate their arguments exactly once. + +#define EXPECT_STREQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual) +#define EXPECT_STRNE(s1, s2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2) +#define EXPECT_STRCASEEQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual) +#define EXPECT_STRCASENE(s1, s2)\ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2) + +#define ASSERT_STREQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual) +#define ASSERT_STRNE(s1, s2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2) +#define ASSERT_STRCASEEQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual) +#define ASSERT_STRCASENE(s1, s2)\ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2) + +// Macros for comparing floating-point numbers. +// +// * {ASSERT|EXPECT}_FLOAT_EQ(expected, actual): +// Tests that two float values are almost equal. +// * {ASSERT|EXPECT}_DOUBLE_EQ(expected, actual): +// Tests that two double values are almost equal. +// * {ASSERT|EXPECT}_NEAR(v1, v2, abs_error): +// Tests that v1 and v2 are within the given distance to each other. +// +// Google Test uses ULP-based comparison to automatically pick a default +// error bound that is appropriate for the operands. See the +// FloatingPoint template class in gtest-internal.h if you are +// interested in the implementation details. + +#define EXPECT_FLOAT_EQ(expected, actual)\ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define EXPECT_DOUBLE_EQ(expected, actual)\ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define ASSERT_FLOAT_EQ(expected, actual)\ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define ASSERT_DOUBLE_EQ(expected, actual)\ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define EXPECT_NEAR(val1, val2, abs_error)\ + EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \ + val1, val2, abs_error) + +#define ASSERT_NEAR(val1, val2, abs_error)\ + ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \ + val1, val2, abs_error) + +// These predicate format functions work on floating-point values, and +// can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g. +// +// EXPECT_PRED_FORMAT2(testing::DoubleLE, Foo(), 5.0); + +// Asserts that val1 is less than, or almost equal to, val2. Fails +// otherwise. In particular, it fails if either val1 or val2 is NaN. +GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2, + float val1, float val2); +GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2, + double val1, double val2); + + +#if GTEST_OS_WINDOWS + +// Macros that test for HRESULT failure and success, these are only useful +// on Windows, and rely on Windows SDK macros and APIs to compile. +// +// * {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}(expr) +// +// When expr unexpectedly fails or succeeds, Google Test prints the +// expected result and the actual result with both a human-readable +// string representation of the error, if available, as well as the +// hex result code. +# define EXPECT_HRESULT_SUCCEEDED(expr) \ + EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr)) + +# define ASSERT_HRESULT_SUCCEEDED(expr) \ + ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr)) + +# define EXPECT_HRESULT_FAILED(expr) \ + EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr)) + +# define ASSERT_HRESULT_FAILED(expr) \ + ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr)) + +#endif // GTEST_OS_WINDOWS + +// Macros that execute statement and check that it doesn't generate new fatal +// failures in the current thread. +// +// * {ASSERT|EXPECT}_NO_FATAL_FAILURE(statement); +// +// Examples: +// +// EXPECT_NO_FATAL_FAILURE(Process()); +// ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed"; +// +#define ASSERT_NO_FATAL_FAILURE(statement) \ + GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_) +#define EXPECT_NO_FATAL_FAILURE(statement) \ + GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_) + +// Causes a trace (including the source file path, the current line +// number, and the given message) to be included in every test failure +// message generated by code in the current scope. The effect is +// undone when the control leaves the current scope. +// +// The message argument can be anything streamable to std::ostream. +// +// In the implementation, we include the current line number as part +// of the dummy variable name, thus allowing multiple SCOPED_TRACE()s +// to appear in the same block - as long as they are on different +// lines. +#define SCOPED_TRACE(message) \ + ::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\ + __FILE__, __LINE__, ::testing::Message() << (message)) + +// Compile-time assertion for type equality. +// StaticAssertTypeEq() compiles iff type1 and type2 are +// the same type. The value it returns is not interesting. +// +// Instead of making StaticAssertTypeEq a class template, we make it a +// function template that invokes a helper class template. This +// prevents a user from misusing StaticAssertTypeEq by +// defining objects of that type. +// +// CAVEAT: +// +// When used inside a method of a class template, +// StaticAssertTypeEq() is effective ONLY IF the method is +// instantiated. For example, given: +// +// template class Foo { +// public: +// void Bar() { testing::StaticAssertTypeEq(); } +// }; +// +// the code: +// +// void Test1() { Foo foo; } +// +// will NOT generate a compiler error, as Foo::Bar() is never +// actually instantiated. Instead, you need: +// +// void Test2() { Foo foo; foo.Bar(); } +// +// to cause a compiler error. +template +bool StaticAssertTypeEq() { + (void)internal::StaticAssertTypeEqHelper(); + return true; +} + +// Defines a test. +// +// The first parameter is the name of the test case, and the second +// parameter is the name of the test within the test case. +// +// The convention is to end the test case name with "Test". For +// example, a test case for the Foo class can be named FooTest. +// +// The user should put his test code between braces after using this +// macro. Example: +// +// TEST(FooTest, InitializesCorrectly) { +// Foo foo; +// EXPECT_TRUE(foo.StatusIsOK()); +// } + +// Note that we call GetTestTypeId() instead of GetTypeId< +// ::testing::Test>() here to get the type ID of testing::Test. This +// is to work around a suspected linker bug when using Google Test as +// a framework on Mac OS X. The bug causes GetTypeId< +// ::testing::Test>() to return different values depending on whether +// the call is from the Google Test framework itself or from user test +// code. GetTestTypeId() is guaranteed to always return the same +// value, as it always calls GetTypeId<>() from the Google Test +// framework. +#define GTEST_TEST(test_case_name, test_name)\ + GTEST_TEST_(test_case_name, test_name, \ + ::testing::Test, ::testing::internal::GetTestTypeId()) + +// Define this macro to 1 to omit the definition of TEST(), which +// is a generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_TEST +# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name) +#endif + +// Defines a test that uses a test fixture. +// +// The first parameter is the name of the test fixture class, which +// also doubles as the test case name. The second parameter is the +// name of the test within the test case. +// +// A test fixture class must be declared earlier. The user should put +// his test code between braces after using this macro. Example: +// +// class FooTest : public testing::Test { +// protected: +// virtual void SetUp() { b_.AddElement(3); } +// +// Foo a_; +// Foo b_; +// }; +// +// TEST_F(FooTest, InitializesCorrectly) { +// EXPECT_TRUE(a_.StatusIsOK()); +// } +// +// TEST_F(FooTest, ReturnsElementCountCorrectly) { +// EXPECT_EQ(0, a_.size()); +// EXPECT_EQ(1, b_.size()); +// } + +#define TEST_F(test_fixture, test_name)\ + GTEST_TEST_(test_fixture, test_name, test_fixture, \ + ::testing::internal::GetTypeId()) + +} // namespace testing + +// Use this function in main() to run all tests. It returns 0 if all +// tests are successful, or 1 otherwise. +// +// RUN_ALL_TESTS() should be invoked after the command line has been +// parsed by InitGoogleTest(). +// +// This function was formerly a macro; thus, it is in the global +// namespace and has an all-caps name. +int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_; + +inline int RUN_ALL_TESTS() { + return ::testing::UnitTest::GetInstance()->Run(); +} + +#endif // GTEST_INCLUDE_GTEST_GTEST_H_ diff --git a/include/monom.h b/include/monom.h new file mode 100644 index 000000000..839c3986d --- /dev/null +++ b/include/monom.h @@ -0,0 +1 @@ +// êëàññ èëè ñòðóêòóðà Ìîíîìà (double êîýôôèöèåíò, öåëàÿ ñâåðíóòàÿ ñòåïåíü) \ No newline at end of file diff --git a/include/polinom.h b/include/polinom.h new file mode 100644 index 000000000..d84a0e895 --- /dev/null +++ b/include/polinom.h @@ -0,0 +1,6 @@ +// êëàññ Ïîëèíîì - óïîðÿäî÷åííûé îäíîñâÿçíûé ñïèñîê Ìîíîìîâ +// ïîääåðæèâàåò îïåðàöèè Ïå÷àòü, Âñòàâêà ìîíîìà, Óäàëåíèå ìîíîìà, +// Ïîèñê ìîíîìà, Ñëîæåíèå ïîëèíîìîâ(ñëèÿíèå óïîðÿäî÷åííûõ ñïèñêîâ), +// Óìíîæåíèå ïîëèíîìîâ + +#include "monom.h" \ No newline at end of file diff --git a/samples/main_polinom.cpp b/samples/main_polinom.cpp new file mode 100644 index 000000000..cf5604773 --- /dev/null +++ b/samples/main_polinom.cpp @@ -0,0 +1,5 @@ +#include "polinom.h" + +void main() +{ +} \ No newline at end of file diff --git a/sln/vc9/gtest/gtest.vcproj b/sln/vc9/gtest/gtest.vcproj new file mode 100644 index 000000000..5d78b7168 --- /dev/null +++ b/sln/vc9/gtest/gtest.vcproj @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sln/vc9/gtest/gtest.vcxproj b/sln/vc9/gtest/gtest.vcxproj new file mode 100644 index 000000000..104363ee2 --- /dev/null +++ b/sln/vc9/gtest/gtest.vcxproj @@ -0,0 +1,84 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {60932AFC-7808-48B7-B3BF-F2BC151C0065} + gtest + Win32Proj + + + + StaticLibrary + v120 + Unicode + true + + + StaticLibrary + v120 + Unicode + + + + + + + + + + + + + <_ProjectFileVersion>12.0.21005.1 + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;GTEST_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + + + MaxSpeed + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;GTEST_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + + + + + + + + + + \ No newline at end of file diff --git a/sln/vc9/gtest/gtest.vcxproj.filters b/sln/vc9/gtest/gtest.vcxproj.filters new file mode 100644 index 000000000..dd2af2286 --- /dev/null +++ b/sln/vc9/gtest/gtest.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/sln/vc9/polinom/polinom.vcproj b/sln/vc9/polinom/polinom.vcproj new file mode 100644 index 000000000..9c9f54d87 --- /dev/null +++ b/sln/vc9/polinom/polinom.vcproj @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sln/vc9/polinom/polinom.vcxproj b/sln/vc9/polinom/polinom.vcxproj new file mode 100644 index 000000000..fa2502e39 --- /dev/null +++ b/sln/vc9/polinom/polinom.vcxproj @@ -0,0 +1,88 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {62061A03-752E-4892-AC65-4B7732128666} + polinom + Win32Proj + + + + StaticLibrary + v120 + Unicode + true + + + StaticLibrary + v120 + Unicode + + + + + + + + + + + + + <_ProjectFileVersion>12.0.21005.1 + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + + Disabled + ../../../include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + + + MaxSpeed + true + ../../../include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sln/vc9/polinom/polinom.vcxproj.filters b/sln/vc9/polinom/polinom.vcxproj.filters new file mode 100644 index 000000000..11a70e4c7 --- /dev/null +++ b/sln/vc9/polinom/polinom.vcxproj.filters @@ -0,0 +1,29 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/sln/vc9/polinoms.sln b/sln/vc9/polinoms.sln new file mode 100644 index 000000000..b6cc689c3 --- /dev/null +++ b/sln/vc9/polinoms.sln @@ -0,0 +1,40 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest", "gtest\gtest.vcxproj", "{60932AFC-7808-48B7-B3BF-F2BC151C0065}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tests", "tests\tests.vcxproj", "{C650C93E-F0A7-4235-9F5F-0DCE78609BFB}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample", "sample\sample.vcxproj", "{5D0218F2-E502-414F-BA66-9E76B2785178}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "polinom", "polinom\polinom.vcxproj", "{62061A03-752E-4892-AC65-4B7732128666}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {60932AFC-7808-48B7-B3BF-F2BC151C0065}.Debug|Win32.ActiveCfg = Debug|Win32 + {60932AFC-7808-48B7-B3BF-F2BC151C0065}.Debug|Win32.Build.0 = Debug|Win32 + {60932AFC-7808-48B7-B3BF-F2BC151C0065}.Release|Win32.ActiveCfg = Release|Win32 + {60932AFC-7808-48B7-B3BF-F2BC151C0065}.Release|Win32.Build.0 = Release|Win32 + {C650C93E-F0A7-4235-9F5F-0DCE78609BFB}.Debug|Win32.ActiveCfg = Debug|Win32 + {C650C93E-F0A7-4235-9F5F-0DCE78609BFB}.Debug|Win32.Build.0 = Debug|Win32 + {C650C93E-F0A7-4235-9F5F-0DCE78609BFB}.Release|Win32.ActiveCfg = Release|Win32 + {C650C93E-F0A7-4235-9F5F-0DCE78609BFB}.Release|Win32.Build.0 = Release|Win32 + {5D0218F2-E502-414F-BA66-9E76B2785178}.Debug|Win32.ActiveCfg = Debug|Win32 + {5D0218F2-E502-414F-BA66-9E76B2785178}.Debug|Win32.Build.0 = Debug|Win32 + {5D0218F2-E502-414F-BA66-9E76B2785178}.Release|Win32.ActiveCfg = Release|Win32 + {5D0218F2-E502-414F-BA66-9E76B2785178}.Release|Win32.Build.0 = Release|Win32 + {62061A03-752E-4892-AC65-4B7732128666}.Debug|Win32.ActiveCfg = Debug|Win32 + {62061A03-752E-4892-AC65-4B7732128666}.Debug|Win32.Build.0 = Debug|Win32 + {62061A03-752E-4892-AC65-4B7732128666}.Release|Win32.ActiveCfg = Release|Win32 + {62061A03-752E-4892-AC65-4B7732128666}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/sln/vc9/sample/sample.vcproj b/sln/vc9/sample/sample.vcproj new file mode 100644 index 000000000..ac4616299 --- /dev/null +++ b/sln/vc9/sample/sample.vcproj @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sln/vc9/sample/sample.vcxproj b/sln/vc9/sample/sample.vcxproj new file mode 100644 index 000000000..66856eb0c --- /dev/null +++ b/sln/vc9/sample/sample.vcxproj @@ -0,0 +1,107 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {5D0218F2-E502-414F-BA66-9E76B2785178} + sample + Win32Proj + + + + Application + v120 + Unicode + true + + + Application + v120 + Unicode + + + + + + + + + + + + + <_ProjectFileVersion>12.0.21005.1 + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + + + + Disabled + ../../../include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + polinom.lib;%(AdditionalDependencies) + ../Debug;%(AdditionalLibraryDirectories) + true + Console + MachineX86 + + + + + MaxSpeed + true + ../../../include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + polinom.lib;%(AdditionalDependencies) + ../Release;%(AdditionalLibraryDirectories) + true + Console + true + true + MachineX86 + + + + + + + + {62061a03-752e-4892-ac65-4b7732128666} + false + + + + + + \ No newline at end of file diff --git a/sln/vc9/sample/sample.vcxproj.filters b/sln/vc9/sample/sample.vcxproj.filters new file mode 100644 index 000000000..9cdc90bbe --- /dev/null +++ b/sln/vc9/sample/sample.vcxproj.filters @@ -0,0 +1,14 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + \ No newline at end of file diff --git a/sln/vc9/tests/tests.vcproj b/sln/vc9/tests/tests.vcproj new file mode 100644 index 000000000..51133e715 --- /dev/null +++ b/sln/vc9/tests/tests.vcproj @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sln/vc9/tests/tests.vcxproj b/sln/vc9/tests/tests.vcxproj new file mode 100644 index 000000000..c9743104a --- /dev/null +++ b/sln/vc9/tests/tests.vcxproj @@ -0,0 +1,113 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {C650C93E-F0A7-4235-9F5F-0DCE78609BFB} + tests + Win32Proj + + + + Application + v120 + Unicode + true + + + Application + v120 + Unicode + + + + + + + + + + + + + <_ProjectFileVersion>12.0.21005.1 + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + + + + Disabled + ../../../gtest;../../../include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + Level3 + EditAndContinue + + + gtest.lib;polinom.lib;%(AdditionalDependencies) + ../Debug;%(AdditionalLibraryDirectories) + true + Console + MachineX86 + + + + + MaxSpeed + true + ../../../gtest;../../../include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + Level3 + ProgramDatabase + + + gtest.lib;polinom.lib;%(AdditionalDependencies) + ../Release;%(AdditionalLibraryDirectories) + true + Console + true + true + MachineX86 + + + + + {60932afc-7808-48b7-b3bf-f2bc151c0065} + true + true + + + {62061a03-752e-4892-ac65-4b7732128666} + false + + + + + + + + + + \ No newline at end of file diff --git a/sln/vc9/tests/tests.vcxproj.filters b/sln/vc9/tests/tests.vcxproj.filters new file mode 100644 index 000000000..9f6c2d1ff --- /dev/null +++ b/sln/vc9/tests/tests.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/src/monom.cpp b/src/monom.cpp new file mode 100644 index 000000000..dbbf93531 --- /dev/null +++ b/src/monom.cpp @@ -0,0 +1 @@ +#include "monom.h" \ No newline at end of file diff --git a/src/polinom.cpp b/src/polinom.cpp new file mode 100644 index 000000000..8852cf8c6 --- /dev/null +++ b/src/polinom.cpp @@ -0,0 +1 @@ +#include "polinom.h" \ No newline at end of file diff --git a/test/test_main.cpp b/test/test_main.cpp new file mode 100644 index 000000000..3968c279a --- /dev/null +++ b/test/test_main.cpp @@ -0,0 +1,6 @@ +#include + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/test_polinom.cpp b/test/test_polinom.cpp new file mode 100644 index 000000000..4a12f5165 --- /dev/null +++ b/test/test_polinom.cpp @@ -0,0 +1,4 @@ +#include +#include "polinom.h" +#include "monom.h" +// òåñòû ìîíîìîâ è ïîëèíîìîâ \ No newline at end of file From b6190acc70c5d8146e6f179eb8e5c7fc76027a7c Mon Sep 17 00:00:00 2001 From: zaharovadasha Date: Thu, 1 Mar 2018 17:33:49 +0300 Subject: [PATCH 2/7] change directory structure --- {gtest => ZaharovaDD/lab1/gtest}/gtest-all.cc | 0 {gtest => ZaharovaDD/lab1/gtest}/gtest.h | 0 {include => ZaharovaDD/lab1/include}/monom.h | 0 {include => ZaharovaDD/lab1/include}/polinom.h | 0 {samples => ZaharovaDD/lab1/samples}/main_polinom.cpp | 0 {sln => ZaharovaDD/lab1/sln}/vc9/gtest/gtest.vcproj | 0 {sln => ZaharovaDD/lab1/sln}/vc9/gtest/gtest.vcxproj | 0 {sln => ZaharovaDD/lab1/sln}/vc9/gtest/gtest.vcxproj.filters | 0 {sln => ZaharovaDD/lab1/sln}/vc9/polinom/polinom.vcproj | 0 {sln => ZaharovaDD/lab1/sln}/vc9/polinom/polinom.vcxproj | 0 {sln => ZaharovaDD/lab1/sln}/vc9/polinom/polinom.vcxproj.filters | 0 {sln => ZaharovaDD/lab1/sln}/vc9/polinoms.sln | 0 {sln => ZaharovaDD/lab1/sln}/vc9/sample/sample.vcproj | 0 {sln => ZaharovaDD/lab1/sln}/vc9/sample/sample.vcxproj | 0 {sln => ZaharovaDD/lab1/sln}/vc9/sample/sample.vcxproj.filters | 0 {sln => ZaharovaDD/lab1/sln}/vc9/tests/tests.vcproj | 0 {sln => ZaharovaDD/lab1/sln}/vc9/tests/tests.vcxproj | 0 {sln => ZaharovaDD/lab1/sln}/vc9/tests/tests.vcxproj.filters | 0 {src => ZaharovaDD/lab1/src}/monom.cpp | 0 {src => ZaharovaDD/lab1/src}/polinom.cpp | 0 {test => ZaharovaDD/lab1/test}/test_main.cpp | 0 {test => ZaharovaDD/lab1/test}/test_polinom.cpp | 0 22 files changed, 0 insertions(+), 0 deletions(-) rename {gtest => ZaharovaDD/lab1/gtest}/gtest-all.cc (100%) rename {gtest => ZaharovaDD/lab1/gtest}/gtest.h (100%) rename {include => ZaharovaDD/lab1/include}/monom.h (100%) rename {include => ZaharovaDD/lab1/include}/polinom.h (100%) rename {samples => ZaharovaDD/lab1/samples}/main_polinom.cpp (100%) rename {sln => ZaharovaDD/lab1/sln}/vc9/gtest/gtest.vcproj (100%) rename {sln => ZaharovaDD/lab1/sln}/vc9/gtest/gtest.vcxproj (100%) rename {sln => ZaharovaDD/lab1/sln}/vc9/gtest/gtest.vcxproj.filters (100%) rename {sln => ZaharovaDD/lab1/sln}/vc9/polinom/polinom.vcproj (100%) rename {sln => ZaharovaDD/lab1/sln}/vc9/polinom/polinom.vcxproj (100%) rename {sln => ZaharovaDD/lab1/sln}/vc9/polinom/polinom.vcxproj.filters (100%) rename {sln => ZaharovaDD/lab1/sln}/vc9/polinoms.sln (100%) rename {sln => ZaharovaDD/lab1/sln}/vc9/sample/sample.vcproj (100%) rename {sln => ZaharovaDD/lab1/sln}/vc9/sample/sample.vcxproj (100%) rename {sln => ZaharovaDD/lab1/sln}/vc9/sample/sample.vcxproj.filters (100%) rename {sln => ZaharovaDD/lab1/sln}/vc9/tests/tests.vcproj (100%) rename {sln => ZaharovaDD/lab1/sln}/vc9/tests/tests.vcxproj (100%) rename {sln => ZaharovaDD/lab1/sln}/vc9/tests/tests.vcxproj.filters (100%) rename {src => ZaharovaDD/lab1/src}/monom.cpp (100%) rename {src => ZaharovaDD/lab1/src}/polinom.cpp (100%) rename {test => ZaharovaDD/lab1/test}/test_main.cpp (100%) rename {test => ZaharovaDD/lab1/test}/test_polinom.cpp (100%) diff --git a/gtest/gtest-all.cc b/ZaharovaDD/lab1/gtest/gtest-all.cc similarity index 100% rename from gtest/gtest-all.cc rename to ZaharovaDD/lab1/gtest/gtest-all.cc diff --git a/gtest/gtest.h b/ZaharovaDD/lab1/gtest/gtest.h similarity index 100% rename from gtest/gtest.h rename to ZaharovaDD/lab1/gtest/gtest.h diff --git a/include/monom.h b/ZaharovaDD/lab1/include/monom.h similarity index 100% rename from include/monom.h rename to ZaharovaDD/lab1/include/monom.h diff --git a/include/polinom.h b/ZaharovaDD/lab1/include/polinom.h similarity index 100% rename from include/polinom.h rename to ZaharovaDD/lab1/include/polinom.h diff --git a/samples/main_polinom.cpp b/ZaharovaDD/lab1/samples/main_polinom.cpp similarity index 100% rename from samples/main_polinom.cpp rename to ZaharovaDD/lab1/samples/main_polinom.cpp diff --git a/sln/vc9/gtest/gtest.vcproj b/ZaharovaDD/lab1/sln/vc9/gtest/gtest.vcproj similarity index 100% rename from sln/vc9/gtest/gtest.vcproj rename to ZaharovaDD/lab1/sln/vc9/gtest/gtest.vcproj diff --git a/sln/vc9/gtest/gtest.vcxproj b/ZaharovaDD/lab1/sln/vc9/gtest/gtest.vcxproj similarity index 100% rename from sln/vc9/gtest/gtest.vcxproj rename to ZaharovaDD/lab1/sln/vc9/gtest/gtest.vcxproj diff --git a/sln/vc9/gtest/gtest.vcxproj.filters b/ZaharovaDD/lab1/sln/vc9/gtest/gtest.vcxproj.filters similarity index 100% rename from sln/vc9/gtest/gtest.vcxproj.filters rename to ZaharovaDD/lab1/sln/vc9/gtest/gtest.vcxproj.filters diff --git a/sln/vc9/polinom/polinom.vcproj b/ZaharovaDD/lab1/sln/vc9/polinom/polinom.vcproj similarity index 100% rename from sln/vc9/polinom/polinom.vcproj rename to ZaharovaDD/lab1/sln/vc9/polinom/polinom.vcproj diff --git a/sln/vc9/polinom/polinom.vcxproj b/ZaharovaDD/lab1/sln/vc9/polinom/polinom.vcxproj similarity index 100% rename from sln/vc9/polinom/polinom.vcxproj rename to ZaharovaDD/lab1/sln/vc9/polinom/polinom.vcxproj diff --git a/sln/vc9/polinom/polinom.vcxproj.filters b/ZaharovaDD/lab1/sln/vc9/polinom/polinom.vcxproj.filters similarity index 100% rename from sln/vc9/polinom/polinom.vcxproj.filters rename to ZaharovaDD/lab1/sln/vc9/polinom/polinom.vcxproj.filters diff --git a/sln/vc9/polinoms.sln b/ZaharovaDD/lab1/sln/vc9/polinoms.sln similarity index 100% rename from sln/vc9/polinoms.sln rename to ZaharovaDD/lab1/sln/vc9/polinoms.sln diff --git a/sln/vc9/sample/sample.vcproj b/ZaharovaDD/lab1/sln/vc9/sample/sample.vcproj similarity index 100% rename from sln/vc9/sample/sample.vcproj rename to ZaharovaDD/lab1/sln/vc9/sample/sample.vcproj diff --git a/sln/vc9/sample/sample.vcxproj b/ZaharovaDD/lab1/sln/vc9/sample/sample.vcxproj similarity index 100% rename from sln/vc9/sample/sample.vcxproj rename to ZaharovaDD/lab1/sln/vc9/sample/sample.vcxproj diff --git a/sln/vc9/sample/sample.vcxproj.filters b/ZaharovaDD/lab1/sln/vc9/sample/sample.vcxproj.filters similarity index 100% rename from sln/vc9/sample/sample.vcxproj.filters rename to ZaharovaDD/lab1/sln/vc9/sample/sample.vcxproj.filters diff --git a/sln/vc9/tests/tests.vcproj b/ZaharovaDD/lab1/sln/vc9/tests/tests.vcproj similarity index 100% rename from sln/vc9/tests/tests.vcproj rename to ZaharovaDD/lab1/sln/vc9/tests/tests.vcproj diff --git a/sln/vc9/tests/tests.vcxproj b/ZaharovaDD/lab1/sln/vc9/tests/tests.vcxproj similarity index 100% rename from sln/vc9/tests/tests.vcxproj rename to ZaharovaDD/lab1/sln/vc9/tests/tests.vcxproj diff --git a/sln/vc9/tests/tests.vcxproj.filters b/ZaharovaDD/lab1/sln/vc9/tests/tests.vcxproj.filters similarity index 100% rename from sln/vc9/tests/tests.vcxproj.filters rename to ZaharovaDD/lab1/sln/vc9/tests/tests.vcxproj.filters diff --git a/src/monom.cpp b/ZaharovaDD/lab1/src/monom.cpp similarity index 100% rename from src/monom.cpp rename to ZaharovaDD/lab1/src/monom.cpp diff --git a/src/polinom.cpp b/ZaharovaDD/lab1/src/polinom.cpp similarity index 100% rename from src/polinom.cpp rename to ZaharovaDD/lab1/src/polinom.cpp diff --git a/test/test_main.cpp b/ZaharovaDD/lab1/test/test_main.cpp similarity index 100% rename from test/test_main.cpp rename to ZaharovaDD/lab1/test/test_main.cpp diff --git a/test/test_polinom.cpp b/ZaharovaDD/lab1/test/test_polinom.cpp similarity index 100% rename from test/test_polinom.cpp rename to ZaharovaDD/lab1/test/test_polinom.cpp From 2e85be0614c419dbaf67772fbc95e89409a48c2a Mon Sep 17 00:00:00 2001 From: zaharovadasha Date: Mon, 4 Jun 2018 19:46:19 +0300 Subject: [PATCH 3/7] itog --- ZaharovaDD/lab1/include/list.h | 170 +++++++++++++ ZaharovaDD/lab1/include/monom.h | 21 +- ZaharovaDD/lab1/include/node.h | 16 ++ ZaharovaDD/lab1/include/polynom.h | 33 +++ ZaharovaDD/lab1/otchet_polynom.docx | Bin 0 -> 113363 bytes ZaharovaDD/lab1/sln/lab1/gtest/gtest.vcxproj | 138 +++++++++++ .../lab1/sln/lab1/gtest/gtest.vcxproj.filters | 23 ++ ZaharovaDD/lab1/sln/lab1/lab1.sln | 65 +++++ .../lab1/sln/lab1/polynom/polynom.vcxproj | 148 +++++++++++ .../sln/lab1/polynom/polynom.vcxproj.filters | 41 ++++ .../lab1/sln/lab1/sample/sample.vcxproj | 163 ++++++++++++ .../sln/lab1/sample/sample.vcxproj.filters | 14 ++ ZaharovaDD/lab1/sln/lab1/test/test.vcxproj | 164 +++++++++++++ .../lab1/sln/lab1/test/test.vcxproj.filters | 20 ++ ZaharovaDD/lab1/src/list.cpp | 1 + ZaharovaDD/lab1/src/node.cpp | 1 + ZaharovaDD/lab1/src/polynom.cpp | 231 ++++++++++++++++++ ZaharovaDD/lab1/test/test_list.cpp | 136 +++++++++++ ZaharovaDD/lab1/test/test_main.cpp | 7 +- ZaharovaDD/lab1/test/test_polynom.cpp | 146 +++++++++++ 20 files changed, 1533 insertions(+), 5 deletions(-) create mode 100644 ZaharovaDD/lab1/include/list.h create mode 100644 ZaharovaDD/lab1/include/node.h create mode 100644 ZaharovaDD/lab1/include/polynom.h create mode 100644 ZaharovaDD/lab1/otchet_polynom.docx create mode 100644 ZaharovaDD/lab1/sln/lab1/gtest/gtest.vcxproj create mode 100644 ZaharovaDD/lab1/sln/lab1/gtest/gtest.vcxproj.filters create mode 100644 ZaharovaDD/lab1/sln/lab1/lab1.sln create mode 100644 ZaharovaDD/lab1/sln/lab1/polynom/polynom.vcxproj create mode 100644 ZaharovaDD/lab1/sln/lab1/polynom/polynom.vcxproj.filters create mode 100644 ZaharovaDD/lab1/sln/lab1/sample/sample.vcxproj create mode 100644 ZaharovaDD/lab1/sln/lab1/sample/sample.vcxproj.filters create mode 100644 ZaharovaDD/lab1/sln/lab1/test/test.vcxproj create mode 100644 ZaharovaDD/lab1/sln/lab1/test/test.vcxproj.filters create mode 100644 ZaharovaDD/lab1/src/list.cpp create mode 100644 ZaharovaDD/lab1/src/node.cpp create mode 100644 ZaharovaDD/lab1/src/polynom.cpp create mode 100644 ZaharovaDD/lab1/test/test_list.cpp create mode 100644 ZaharovaDD/lab1/test/test_polynom.cpp diff --git a/ZaharovaDD/lab1/include/list.h b/ZaharovaDD/lab1/include/list.h new file mode 100644 index 000000000..fe5a668ba --- /dev/null +++ b/ZaharovaDD/lab1/include/list.h @@ -0,0 +1,170 @@ +#pragma once +#include "node.h" +#include + +using namespace std; + +//Шаблон клаÑÑа ЦикличеÑкий ÑпиÑок Ñ Ð³Ð¾Ð»Ð¾Ð²Ð¾Ð¹ +template +class list +{ +private: + node* head; //голова + node* Curr; //Указатель на текущий +public: + list(); //К. по умолчанию + ~list(); //ДеÑтруктор + list(const list& a); //К. + void Clean(); //очиÑтка ÑпиÑка + + void InsertInOrder(const TP& a); //Ð’Ñтавить в упорÑдоченный ÑпиÑок + void InsertAfter(node* a1, const TP& a2); //вÑтавить поÑле + void InsertToTail(const TP a); //вÑтавить в конец + + bool IsEmpty() const { return (head->next == head); }; //проверка на пуÑтоту + //напиÑать метод isfull + TP& GetCurr() const { return Curr->data; } //Получение текущего адреÑа + void Reset() { Curr = head->next; } //УÑтановка на начало + void gonext() { Curr = Curr->next; }; //переход на Ñледующее звено + bool IsOver() { if (Curr->next == head->next) return true; else return false; } //проверка на конец + + const list& operator=(const list& a); //Перегрузка оператора = + + bool operator==(const list& a) const; //Оператор ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ == + bool operator!=(const list& a) const { return !(*this == a); } //Оператор ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ Ð½Ðµ равно +}; + + +template //К. по умолчанию +list::list() +{ + head = new node(); + Curr = head->next; + head->next = head; +} + +template +list::~list() +{ + Clean(); + delete head; +} + + +template //К. ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ +list::list(const list& a) +{ + head = new node; + node* E1 = a.head; + node* E2 = head; + if (E1->next == a.head) + { + head->next = head; + return; + } + while (E1->next != a.head) + { + E1 = E1->next; + E2->next = new node(E1->data); + E2 = E2->next; + } + E2->next = head; + Curr = head->next; +} + +template //ОчиÑтка ÑпиÑка +void list::Clean() +{ + node* curr = head->next; + while (curr != head) + { + node* temp = curr->next; + delete curr; + curr = temp; + } + head->next = head; +} + + +template //Ð’Ñтавить в упорÑдоченный ÑпиÑок +void list::InsertInOrder(const TP& a) +{ + if (IsEmpty()) + { + head->next = new node(a); + head->next->next = head; + } + else + { + node* t = new node(a); + node* c = head; + + while (c->next != head && (*(c->next) < *t)) + { + c = c->next; + } + node* t1 = c->next; + c->next = t; + c->next->next = t1; + } +} + +template //вÑтавить поÑле +void list::InsertAfter(node* a1, const TP& a2) +{ + if (head == NULL) + throw "empty list"; + else + { + node* t = a1->next; + a1->next = new node(a2, t); + } +} + +template //вÑтавить в конец +void list ::InsertToTail(const TP a) +{ + Reset(); + while (Curr->next != head) + gonext(); + node* t = Curr->next; + Curr->next = new node(a); + Curr->next->next = t; +} + +template //приÑваивание +const list& list::operator=(const list& a) +{ + Clean(); + node* p_a = a.head; + node* p_curr = head; + while (p_a->next != a.head) + { + p_a = p_a->next; + p_curr->next = new node(p_a->data); + p_curr = p_curr->next; + } + p_curr->next = head; + Curr = head->next; + return *this; +} + + +template //Ñравнение +bool list::operator==(const list& a) const +{ + bool res = true; + if (this != &a) + { + node* t1 = a.head->next; + node* t2 = head->next; + while (t1->data == t2->data && t2 != head && t1 != a.head) + { + t1 = t1->next; + t2 = t2->next; + } + if (t2 != head || t1 != a.head) + res = false; + } + return res; +} diff --git a/ZaharovaDD/lab1/include/monom.h b/ZaharovaDD/lab1/include/monom.h index 839c3986d..40b26b11f 100644 --- a/ZaharovaDD/lab1/include/monom.h +++ b/ZaharovaDD/lab1/include/monom.h @@ -1 +1,20 @@ -// êëàññ èëè ñòðóêòóðà Ìîíîìà (double êîýôôèöèåíò, öåëàÿ ñâåðíóòàÿ ñòåïåíü) \ No newline at end of file +#pragma once +#include + + +class monom +{ +public: + double cff; //Êîýôô. ïåðåä ìîíîìîì + int svr; //Ñâ¸ðíóòàÿ ñòåïåíü + + monom(const monom& a) { cff = a.cff; svr = a.svr; } + monom(const double index_cff = 0.0, const unsigned int index_svr = 0) { cff = index_cff; svr = index_svr; } //Ê. + const monom& operator=(const monom& a) { cff = a.cff; svr = a.svr; return *this; } //Î. ïðèñâàèâàíèÿ + bool operator< (const monom& a) const { return (svr (const monom& a) const { return (svr>a.svr); } //Î. ñðàâíåíèÿ + bool operator==(const monom& a) const { return ((svr == a.svr) && (cff == a.cff)); } //ïåðåãðóæåíî == + bool operator!=(const monom& a) const { return !(*this == a); } //ïåðåãðóæåíî != + + +}; diff --git a/ZaharovaDD/lab1/include/node.h b/ZaharovaDD/lab1/include/node.h new file mode 100644 index 000000000..66f51b1c9 --- /dev/null +++ b/ZaharovaDD/lab1/include/node.h @@ -0,0 +1,16 @@ +#pragma once + +//Шаблон клаÑÑа "Элемент ÑпиÑка" +template +class node +{ +public: + TP data; //Данные в Ñл. + node* next; //Указатель на Ñледующий Ñл. + + node() { next = NULL; }; //К. по умолчанию + node(TP a1, node* a2 = NULL) { data = a1; next = a2; }; //К. Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð¾Ð¼ + bool operator< (const node& a) const { return (data < a.data); }; //О. ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ + bool operator> (const node& a) const { return (data > a.data); }; //О. ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ +}; + diff --git a/ZaharovaDD/lab1/include/polynom.h b/ZaharovaDD/lab1/include/polynom.h new file mode 100644 index 000000000..48e9ff458 --- /dev/null +++ b/ZaharovaDD/lab1/include/polynom.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include +#include "monom.h" +#include "list.h" + +#define OFFSET 120 //Код Ñимвола 'x' + +class polynom +{ +private: + list list_monom; //ÑпиÑок мономов + list such(list & op); //объединение подобные + +public: + polynom(const polynom& p); + const polynom& operator=(const polynom &p); + polynom(list &in_list) : list_monom(in_list) {} //К. по ÑпиÑку + polynom(const string op = ""); //К. по Ñтроке + + polynom operator-(const polynom& p) const { return *this + p*(-1); } //Бинарный Ð¼Ð¸Ð½ÑƒÑ + polynom operator-() const { return (-1)*(*this); } //Унарный Ð¼Ð¸Ð½ÑƒÑ + bool operator==(const polynom& p) const { return list_monom == p.list_monom; } //О. ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ + bool operator!=(const polynom& p) const { return list_monom != p.list_monom; } //О. ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ + polynom operator+(const polynom& p) const; //О. ÑÐ»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»Ð¸Ð½Ð¾Ð¼Ð¾Ð² + polynom operator*(const polynom& p) const; //О. ÑƒÐ¼Ð½Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»Ð¸Ð½Ð¾Ð¼Ð¾Ð² + polynom operator*(const double k) const; //Умножение на конÑтанту + friend polynom operator*(const double k, const polynom& p) { return p*k; } //Умножение на конÑтанту Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð¹ Ñтороны + + friend std::ostream& operator<<(std::ostream &str, const polynom &p); //О. вÑтавки в поток +}; \ No newline at end of file diff --git a/ZaharovaDD/lab1/otchet_polynom.docx b/ZaharovaDD/lab1/otchet_polynom.docx new file mode 100644 index 0000000000000000000000000000000000000000..4c61763cef208221a09dd15de6fecc1e66d0a299 GIT binary patch literal 113363 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 WNI+u*fe3+5G7<7`8EJk1 literal 0 HcmV?d00001 diff --git a/ZaharovaDD/lab1/sln/lab1/gtest/gtest.vcxproj b/ZaharovaDD/lab1/sln/lab1/gtest/gtest.vcxproj new file mode 100644 index 000000000..7bad67553 --- /dev/null +++ b/ZaharovaDD/lab1/sln/lab1/gtest/gtest.vcxproj @@ -0,0 +1,138 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + {6868F283-1082-4B28-BD23-6B7E1A9DC025} + Win32Proj + gtest + 8.1 + + + + StaticLibrary + true + v140 + Unicode + + + StaticLibrary + false + v140 + true + Unicode + + + StaticLibrary + true + v140 + Unicode + + + StaticLibrary + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/ZaharovaDD/lab1/sln/lab1/gtest/gtest.vcxproj.filters b/ZaharovaDD/lab1/sln/lab1/gtest/gtest.vcxproj.filters new file mode 100644 index 000000000..926637662 --- /dev/null +++ b/ZaharovaDD/lab1/sln/lab1/gtest/gtest.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + + + Заголовочные файлы + + + + + Файлы иÑходного кода + + + \ No newline at end of file diff --git a/ZaharovaDD/lab1/sln/lab1/lab1.sln b/ZaharovaDD/lab1/sln/lab1/lab1.sln new file mode 100644 index 000000000..02bbd7e05 --- /dev/null +++ b/ZaharovaDD/lab1/sln/lab1/lab1.sln @@ -0,0 +1,65 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest", "gtest\gtest.vcxproj", "{6868F283-1082-4B28-BD23-6B7E1A9DC025}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "polynom", "polynom\polynom.vcxproj", "{86281C14-AE33-4BDA-B61B-CC884EB2FF21}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "samples", "sample\sample.vcxproj", "{B8747A82-1DFA-4CF0-BFA3-1CB9A5873957}" + ProjectSection(ProjectDependencies) = postProject + {86281C14-AE33-4BDA-B61B-CC884EB2FF21} = {86281C14-AE33-4BDA-B61B-CC884EB2FF21} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcxproj", "{45E38963-7935-48BC-BB02-6D6C17BC06A7}" + ProjectSection(ProjectDependencies) = postProject + {86281C14-AE33-4BDA-B61B-CC884EB2FF21} = {86281C14-AE33-4BDA-B61B-CC884EB2FF21} + {6868F283-1082-4B28-BD23-6B7E1A9DC025} = {6868F283-1082-4B28-BD23-6B7E1A9DC025} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6868F283-1082-4B28-BD23-6B7E1A9DC025}.Debug|x64.ActiveCfg = Debug|x64 + {6868F283-1082-4B28-BD23-6B7E1A9DC025}.Debug|x64.Build.0 = Debug|x64 + {6868F283-1082-4B28-BD23-6B7E1A9DC025}.Debug|x86.ActiveCfg = Debug|Win32 + {6868F283-1082-4B28-BD23-6B7E1A9DC025}.Debug|x86.Build.0 = Debug|Win32 + {6868F283-1082-4B28-BD23-6B7E1A9DC025}.Release|x64.ActiveCfg = Release|x64 + {6868F283-1082-4B28-BD23-6B7E1A9DC025}.Release|x64.Build.0 = Release|x64 + {6868F283-1082-4B28-BD23-6B7E1A9DC025}.Release|x86.ActiveCfg = Release|Win32 + {6868F283-1082-4B28-BD23-6B7E1A9DC025}.Release|x86.Build.0 = Release|Win32 + {86281C14-AE33-4BDA-B61B-CC884EB2FF21}.Debug|x64.ActiveCfg = Debug|x64 + {86281C14-AE33-4BDA-B61B-CC884EB2FF21}.Debug|x64.Build.0 = Debug|x64 + {86281C14-AE33-4BDA-B61B-CC884EB2FF21}.Debug|x86.ActiveCfg = Debug|Win32 + {86281C14-AE33-4BDA-B61B-CC884EB2FF21}.Debug|x86.Build.0 = Debug|Win32 + {86281C14-AE33-4BDA-B61B-CC884EB2FF21}.Release|x64.ActiveCfg = Release|x64 + {86281C14-AE33-4BDA-B61B-CC884EB2FF21}.Release|x64.Build.0 = Release|x64 + {86281C14-AE33-4BDA-B61B-CC884EB2FF21}.Release|x86.ActiveCfg = Release|Win32 + {86281C14-AE33-4BDA-B61B-CC884EB2FF21}.Release|x86.Build.0 = Release|Win32 + {B8747A82-1DFA-4CF0-BFA3-1CB9A5873957}.Debug|x64.ActiveCfg = Debug|x64 + {B8747A82-1DFA-4CF0-BFA3-1CB9A5873957}.Debug|x64.Build.0 = Debug|x64 + {B8747A82-1DFA-4CF0-BFA3-1CB9A5873957}.Debug|x86.ActiveCfg = Debug|Win32 + {B8747A82-1DFA-4CF0-BFA3-1CB9A5873957}.Debug|x86.Build.0 = Debug|Win32 + {B8747A82-1DFA-4CF0-BFA3-1CB9A5873957}.Release|x64.ActiveCfg = Release|x64 + {B8747A82-1DFA-4CF0-BFA3-1CB9A5873957}.Release|x64.Build.0 = Release|x64 + {B8747A82-1DFA-4CF0-BFA3-1CB9A5873957}.Release|x86.ActiveCfg = Release|Win32 + {B8747A82-1DFA-4CF0-BFA3-1CB9A5873957}.Release|x86.Build.0 = Release|Win32 + {45E38963-7935-48BC-BB02-6D6C17BC06A7}.Debug|x64.ActiveCfg = Debug|x64 + {45E38963-7935-48BC-BB02-6D6C17BC06A7}.Debug|x64.Build.0 = Debug|x64 + {45E38963-7935-48BC-BB02-6D6C17BC06A7}.Debug|x86.ActiveCfg = Debug|Win32 + {45E38963-7935-48BC-BB02-6D6C17BC06A7}.Debug|x86.Build.0 = Debug|Win32 + {45E38963-7935-48BC-BB02-6D6C17BC06A7}.Release|x64.ActiveCfg = Release|x64 + {45E38963-7935-48BC-BB02-6D6C17BC06A7}.Release|x64.Build.0 = Release|x64 + {45E38963-7935-48BC-BB02-6D6C17BC06A7}.Release|x86.ActiveCfg = Release|Win32 + {45E38963-7935-48BC-BB02-6D6C17BC06A7}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ZaharovaDD/lab1/sln/lab1/polynom/polynom.vcxproj b/ZaharovaDD/lab1/sln/lab1/polynom/polynom.vcxproj new file mode 100644 index 000000000..ffd12da3a --- /dev/null +++ b/ZaharovaDD/lab1/sln/lab1/polynom/polynom.vcxproj @@ -0,0 +1,148 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + {86281C14-AE33-4BDA-B61B-CC884EB2FF21} + Win32Proj + polynom + 8.1 + + + + StaticLibrary + true + v140 + Unicode + + + StaticLibrary + false + v140 + true + Unicode + + + StaticLibrary + true + v140 + Unicode + + + StaticLibrary + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\include + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\include + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\include + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + ..\..\..\include + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/ZaharovaDD/lab1/sln/lab1/polynom/polynom.vcxproj.filters b/ZaharovaDD/lab1/sln/lab1/polynom/polynom.vcxproj.filters new file mode 100644 index 000000000..5c7fd75c3 --- /dev/null +++ b/ZaharovaDD/lab1/sln/lab1/polynom/polynom.vcxproj.filters @@ -0,0 +1,41 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + \ No newline at end of file diff --git a/ZaharovaDD/lab1/sln/lab1/sample/sample.vcxproj b/ZaharovaDD/lab1/sln/lab1/sample/sample.vcxproj new file mode 100644 index 000000000..c4470501c --- /dev/null +++ b/ZaharovaDD/lab1/sln/lab1/sample/sample.vcxproj @@ -0,0 +1,163 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + {B8747A82-1DFA-4CF0-BFA3-1CB9A5873957} + Win32Proj + sample + 8.1 + samples + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\include + + + Console + true + ..\Debug + polynom.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\include + + + Console + true + ..\Debug + polynom.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\include + + + Console + true + true + true + ..\Release + polynom.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\include + + + Console + true + true + true + ..\Release + polynom.lib;%(AdditionalDependencies) + + + + + + \ No newline at end of file diff --git a/ZaharovaDD/lab1/sln/lab1/sample/sample.vcxproj.filters b/ZaharovaDD/lab1/sln/lab1/sample/sample.vcxproj.filters new file mode 100644 index 000000000..689f4211a --- /dev/null +++ b/ZaharovaDD/lab1/sln/lab1/sample/sample.vcxproj.filters @@ -0,0 +1,14 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Файлы иÑходного кода + + + \ No newline at end of file diff --git a/ZaharovaDD/lab1/sln/lab1/test/test.vcxproj b/ZaharovaDD/lab1/sln/lab1/test/test.vcxproj new file mode 100644 index 000000000..2de3d4bb4 --- /dev/null +++ b/ZaharovaDD/lab1/sln/lab1/test/test.vcxproj @@ -0,0 +1,164 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + {45E38963-7935-48BC-BB02-6D6C17BC06A7} + Win32Proj + test + 8.1 + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\include;..\..\..\gtest + + + Console + true + ..\Debug + polynom.lib;gtest.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\include;..\..\..\gtest + + + Console + true + ..\Debug + polynom.lib;gtest.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\include;..\..\..\gtest + + + Console + true + true + true + ..\Release + polynom.lib;gtest.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\include;..\..\..\gtest + + + Console + true + true + true + ..\Release + polynom.lib;gtest.lib;%(AdditionalDependencies) + + + + + + \ No newline at end of file diff --git a/ZaharovaDD/lab1/sln/lab1/test/test.vcxproj.filters b/ZaharovaDD/lab1/sln/lab1/test/test.vcxproj.filters new file mode 100644 index 000000000..ecaa94698 --- /dev/null +++ b/ZaharovaDD/lab1/sln/lab1/test/test.vcxproj.filters @@ -0,0 +1,20 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + \ No newline at end of file diff --git a/ZaharovaDD/lab1/src/list.cpp b/ZaharovaDD/lab1/src/list.cpp new file mode 100644 index 000000000..c1d8a57a9 --- /dev/null +++ b/ZaharovaDD/lab1/src/list.cpp @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/ZaharovaDD/lab1/src/node.cpp b/ZaharovaDD/lab1/src/node.cpp new file mode 100644 index 000000000..eed307217 --- /dev/null +++ b/ZaharovaDD/lab1/src/node.cpp @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/ZaharovaDD/lab1/src/polynom.cpp b/ZaharovaDD/lab1/src/polynom.cpp new file mode 100644 index 000000000..975297297 --- /dev/null +++ b/ZaharovaDD/lab1/src/polynom.cpp @@ -0,0 +1,231 @@ +#include "polynom.h" + +using namespace std; + +list polynom::such(list & op) +{ + list res; + res.Reset(); + op.Reset(); + node mon(op.GetCurr().cff); + list y(op); + while (!op.IsOver()) + { + mon.data.svr = op.GetCurr().svr; + y.gonext(); + if (op.GetCurr().svr == y.GetCurr().svr && (y.GetCurr().cff || y.GetCurr().svr)) + mon.data.cff += y.GetCurr().cff; + else + { + if (mon.data.cff) + { + res.InsertToTail(mon.data); + res.gonext(); + } + mon.data.cff = y.GetCurr().cff; + } + op.gonext(); + } + return res; +} + +polynom::polynom(const polynom& p) +{ + list_monom = p.list_monom; +} + +polynom::polynom(string op) +{ + int d[3] = { 100,10,1 }; + while (op.length()) + { + string pt; + monom t; + int pos = 1; + while (pos < op.length() && op[pos] != '+' && op[pos] != '-') + pos++; + pt = op.substr(0, pos); //áåðåò ñ íóëåâîé ïîçèöèè pos ýë-òîâ + op.erase(0, pos); //Óäàëÿåò ýëåìåíòû â äèàïàçîíå + pos = 0; + while (pt[pos] != 'x' && pt[pos] != 'y' && pt[pos] != 'z' && pos < pt.length()) + pos++; + + string pstr = pt.substr(0, pos); + if (pstr == "+" || pstr.length() == 0) + t.cff = 1; + else if (pstr == "-") + t.cff = -1; + else t.cff = stod(pstr); //ïðåîáðàçîâàíèå ñòðîêè â ÷èñëî + + pt.erase(0, pos); + pt += ' '; + + for (int i = 0; i < 3; i++) + { + pos = pt.find((char)(OFFSET + i)); + if (pos > -1) + { + if (pt[pos + 1] != '^') + pt.insert(pos + 1, "^1"); + t.svr += d[i] * stoi(pt.substr(pos + 2, 1)); // ïðåîáðàçóåò ïîñëåäîâàòåëüíîñòü ýëåìåíòîâ â öåëîå ÷èñëî. + pt.erase(pos, 3); + } + } + + list_monom.InsertInOrder(t); + } + + list_monom = such(list_monom); +} + + +const polynom & polynom::operator=(const polynom & p) +{ + list_monom = p.list_monom; + return *this; +} + +polynom polynom::operator+(const polynom& p) const +{ + + polynom res; + polynom pthis = *this; + polynom pol = p; + + pthis.list_monom.Reset(); + pol.list_monom.Reset(); + res.list_monom.Reset(); + + while (!pthis.list_monom.IsOver() && !pol.list_monom.IsOver()) + { + if (pthis.list_monom.GetCurr() > pol.list_monom.GetCurr()) //óïîðÿäî÷èâàíèå + { + res.list_monom.InsertToTail(pol.list_monom.GetCurr()); + pol.list_monom.gonext(); + res.list_monom.gonext(); + } + else if (pthis.list_monom.GetCurr() < pol.list_monom.GetCurr()) + { + res.list_monom.InsertToTail(pthis.list_monom.GetCurr()); + pthis.list_monom.gonext(); + res.list_monom.gonext(); + } + else + { + double new_c = pthis.list_monom.GetCurr().cff + pol.list_monom.GetCurr().cff; + if (new_c) + { + res.list_monom.InsertToTail(monom(new_c, pthis.list_monom.GetCurr().svr)); + res.list_monom.gonext(); + } + pthis.list_monom.gonext(); + pol.list_monom.gonext(); + } + } + while (!pthis.list_monom.IsOver()) + { + res.list_monom.InsertToTail(pthis.list_monom.GetCurr()); + pthis.list_monom.gonext(); + res.list_monom.gonext(); + } + while (!pol.list_monom.IsOver()) + { + res.list_monom.InsertToTail(pol.list_monom.GetCurr()); + pol.list_monom.gonext(); + res.list_monom.gonext(); + } + + return res; +} + +polynom polynom::operator*(const polynom& p) const +{ + + polynom res; + polynom pth = *this; + polynom pol = p; + + pth.list_monom.Reset(); + pol.list_monom.Reset(); + + while (!pth.list_monom.IsOver()) + { + double pth_cff = pth.list_monom.GetCurr().cff; + int pth_svr = pth.list_monom.GetCurr().svr; + polynom tp(p); + tp.list_monom.Reset(); + while (!tp.list_monom.IsOver()) + { + int tp_svr = tp.list_monom.GetCurr().svr; + if ((tp_svr % 10 + pth_svr % 10) < 10 && (tp_svr / 10 % 10 + pth_svr / 10 % 10) < 10 && (tp_svr / 100 + pth_svr / 100) < 10) //îñòàòîê îò äåëåíèÿ + { + tp.list_monom.GetCurr().svr += pth_svr; + tp.list_monom.GetCurr().cff *= pth_cff; + } + else + throw "Error"; + tp.list_monom.gonext(); + } + res = res + tp; + pth.list_monom.gonext(); + } + return res; +} + +polynom polynom::operator*(const double k) const +{ + polynom res; + res = *this; + res.list_monom.Reset(); + while (!res.list_monom.IsOver()) + { + res.list_monom.GetCurr().cff *= k; + res.list_monom.gonext(); + } + return res; +} + +ostream& operator<<(ostream &str, const polynom& p) +{ + polynom pl = p; + pl.list_monom.Reset(); + + while (!pl.list_monom.IsOver()) + { + + monom tp = pl.list_monom.GetCurr(); + + if (tp.cff > 0) + { + str << "+"; + if (tp.cff == 1 && tp.svr == 0) + str << "1"; + else + if (tp.cff != 1) + str << tp.cff; + } + else + str << tp.cff; + + int a = tp.svr / 100; + if (a>1) + str << "x^" << a; + else + if (a == 1) + str << "x"; + a = tp.svr / 10 % 10; + if (a>1) + str << "y^" << a; + else + if (a == 1) + str << "y"; + a = tp.svr % 10; + if (a>1) + str << "z^" << a; + else + if (a == 1) + str << "z"; + pl.list_monom.gonext(); + } + return str; +} diff --git a/ZaharovaDD/lab1/test/test_list.cpp b/ZaharovaDD/lab1/test/test_list.cpp new file mode 100644 index 000000000..ba16d596d --- /dev/null +++ b/ZaharovaDD/lab1/test/test_list.cpp @@ -0,0 +1,136 @@ +#include "gtest.h" +#include "list.h" + +TEST(lists, create_empty_list) +{ + ASSERT_NO_THROW(list m); +} + +class List : public ::testing::Test { +protected: + list l; + list l2; + +public: + List() + { + l2.InsertInOrder(10); + l2.InsertInOrder(15); + } + + ~List() {} +}; + +TEST_F(List, created_empty_list_is_correct) +{ + EXPECT_EQ(true, l.IsEmpty()); +} + +TEST_F(List, copy_empty_list) +{ + ASSERT_NO_THROW(list n(l)); +} + +TEST_F(List, copied_empty_list_is_correct) +{ + list n(l); + EXPECT_EQ(true, n.IsEmpty()); +} + +TEST_F(List, assign_empty_list) +{ + ASSERT_NO_THROW(list n = l); +} + +TEST_F(List, assigned_empty_list_is_correct) +{ + list n = l; + EXPECT_EQ(true, n.IsEmpty()); +} + +TEST_F(List, insert_in_empty_list) +{ + ASSERT_NO_THROW(l.InsertInOrder(10)); +} + +TEST_F(List, insert_in_empty_list_is_correct) +{ + l.InsertInOrder(10); + l.Reset(); + EXPECT_EQ(10, l.GetCurr()); + l.gonext(); + l.gonext(); + EXPECT_EQ(l.GetCurr(), l.GetCurr()); +} + +TEST_F(List, compare_list_with_itself) +{ + EXPECT_EQ(true, l == l); +} + +TEST_F(List, empty_lists_are_equal) +{ + list n(l); + EXPECT_EQ(true, n == l); +} + +TEST_F(List, copy_full_list) +{ + ASSERT_NO_THROW(list n(l2)); +} + +TEST_F(List, assign_full_list) +{ + ASSERT_NO_THROW(list n = l2); +} + +TEST_F(List, insert_in_the_beginning) +{ + l2.InsertInOrder(0); + l2.Reset(); + EXPECT_EQ(0, l2.GetCurr()); + l2.gonext(); + EXPECT_EQ(10, l2.GetCurr()); + l2.Reset(); + EXPECT_EQ(0, l2.GetCurr()); +} + +TEST_F(List, insert_in_the_middle) +{ + l2.InsertInOrder(15); + l2.Reset(); + EXPECT_EQ(10, l2.GetCurr()); + l2.gonext(); + EXPECT_EQ(15, l2.GetCurr()); + EXPECT_EQ(15, l2.GetCurr()); +} + + +TEST_F(List, full_lists_are_equal1) +{ + list n(l2); + EXPECT_EQ(true, n == l2); +} + +TEST_F(List, full_lists_are_equal2) +{ + list n(l2); + EXPECT_EQ(true, n == l2); +} + +TEST_F(List, full_lists_are_equal3) +{ + list n(l2); + EXPECT_EQ(true, n == l2); +} + +TEST_F(List, empty_and_full_lists_are_not_equal) +{ + EXPECT_NE(true, l2 == l); +} + +TEST_F(List, lists_with_different_sizes_and_same_beginnings_are_not_equal) +{ + l.InsertInOrder(1); + EXPECT_NE(true, l2 == l); +} \ No newline at end of file diff --git a/ZaharovaDD/lab1/test/test_main.cpp b/ZaharovaDD/lab1/test/test_main.cpp index 3968c279a..c0e7e7ade 100644 --- a/ZaharovaDD/lab1/test/test_main.cpp +++ b/ZaharovaDD/lab1/test/test_main.cpp @@ -1,6 +1,5 @@ #include - int main(int argc, char **argv) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/ZaharovaDD/lab1/test/test_polynom.cpp b/ZaharovaDD/lab1/test/test_polynom.cpp new file mode 100644 index 000000000..a8cc5dab0 --- /dev/null +++ b/ZaharovaDD/lab1/test/test_polynom.cpp @@ -0,0 +1,146 @@ +#include "gtest.h" +#include "polynom.h" + + +using namespace std; +TEST(polynom, check_build_polinom) +{ + + ASSERT_NO_THROW(polynom a("x+2")); +} + + +TEST(polynom, degree_not_more_than_9_1) +{ + polynom a("x^5"), b("x^4"); + ASSERT_NO_THROW(a*b); +} + +struct parse_test +{ + string str; + polynom res; + parse_test(string istr, const vector &ms) + { + str = istr; + list temp; + for (int i = 0; i < ms.size(); i++) + temp.InsertInOrder(ms[i]); + res = polynom(temp); + } +}; + +class pol_parse : public ::testing::TestWithParam +{ +protected: polynom a_test; +public: + pol_parse() : a_test(GetParam().str) + { + } + ~pol_parse() {} +}; + +TEST_P(pol_parse, correct_parse_of_polynom_strings) +{ + EXPECT_EQ(GetParam().res, a_test); +} + + +struct calc_test +{ + string left; + string right; + double c; + string res; + calc_test(string ires, string il, string ir = "", double ic = 0) + { + left = il; + right = ir; + c = ic; + res = ires; + } +}; + + + + +class pol_plus : public ::testing::TestWithParam +{ +protected: polynom pl, pr, pres; +public: + pol_plus() : pl(GetParam().left), pr(GetParam().right), pres(GetParam().res) + { + } + ~pol_plus() {} +}; + +TEST_P(pol_plus, polynom_plus_polynom) +{ + EXPECT_EQ(pres, pl + pr); +} + +INSTANTIATE_TEST_CASE_P(Inst2, + pol_plus, + ::testing::Values( + calc_test("2x+2y", "2x", "2y"), + calc_test("10x", "10x", ""), + calc_test("2x", "-4x", "6x"), + calc_test("", "-20.5xy", "20.5xy"), + calc_test("10xy^2", "7x^2y", "10xy^2-7x^2y"), + calc_test("1+x+2y+3z", "1+x+2y", "3z"), + calc_test("", "10.1", "-10.1"), + calc_test("", "0", "0"), + calc_test("0", "2.7z", "-2.7z"), + calc_test("2x-15y+30", "x", "-15y+30+x") + )); + +TEST(polynom, power_is_more_than_9_while_mult) +{ + polynom a("x^5"), b("x^5"); + ASSERT_ANY_THROW(a*b); +} + + + + +class pol_mult : public ::testing::TestWithParam +{ +protected: polynom pl, pr, pres; +public: + pol_mult() : pl(GetParam().left), pr(GetParam().right), pres(GetParam().res) + { + } + ~pol_mult() {} +}; + +TEST_P(pol_mult, polynom_mult_polynom) +{ + EXPECT_EQ(pres, pl * pr); +} + +INSTANTIATE_TEST_CASE_P(Inst3, + pol_mult, + ::testing::Values( + calc_test("6xy", "3x", "2y"), + calc_test("25", "5", "5"), + calc_test("20xy^3", "5y^3", "4x"), + calc_test("3x+3y^2+3x^2-3xy^2-6y^4", "3+3x-6y^2", "x+y^2"), + calc_test("x^2y^2", "-x^2", "-y^2"), + calc_test("x^2y^2z+x^2y^2z^2", "xyz", "xyz+xy"), + calc_test("9-x^2", "3-x", "3+x"), + calc_test("10xy+x^2y^2+2x^3+5y^3", "x^2+5y", "2x+y^2") + )); + + + + +class c_mult : public ::testing::TestWithParam +{ +protected: polynom p, pres; double cn; +public: + c_mult() : p(GetParam().left), pres(GetParam().res) + { + cn = GetParam().c; + } + ~c_mult() {} +}; \ No newline at end of file From b7da7c7f774572ea03d1f1af7b61638090074a98 Mon Sep 17 00:00:00 2001 From: zaharovadasha Date: Mon, 4 Jun 2018 19:58:23 +0300 Subject: [PATCH 4/7] itog --- ZaharovaDD/lab1/samples/main_polynom.cpp | 66 ++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 ZaharovaDD/lab1/samples/main_polynom.cpp diff --git a/ZaharovaDD/lab1/samples/main_polynom.cpp b/ZaharovaDD/lab1/samples/main_polynom.cpp new file mode 100644 index 000000000..43857d3b7 --- /dev/null +++ b/ZaharovaDD/lab1/samples/main_polynom.cpp @@ -0,0 +1,66 @@ +#include "monom.h" +#include "polynom.h" +#include + +using namespace std; + +void main() +{ + int flag = 1; + int k = 0; + while (flag == 1) + { + system("cls");//î÷èñòèòü ýêðàí + cout << "Write first polynom" << endl; + string s1; + cin >> s1; + polynom S1(s1); + cout << "Write second polynom" << endl; + string s2; + cin >> s2; + polynom S2(s2); + cout << "Choose operation" << endl; + cout << "1 +" << endl; + cout << "2 -" << endl; + cout << "3 *" << endl; + cout << "4 * const" << endl; + cin >> k; + switch (k) + { + case 1: + { + polynom res = S1 + S2; + cout << res; + break; + } + case 2: + { + polynom res = S1 - S2; + cout << res; + break; + } + case 3: + { + polynom res = S1 * S2; + cout << res; + break; + } + case 4: + { + string con; + cout << " Write const" << endl; + cin >> con; + polynom C(con); + polynom res = C*S1; + cout << res; + break; + } + default: + break; + } + + cout << " \n Repead : 1" << endl; + cin >> flag; + + } +} \ No newline at end of file From 99f184c756bbf45c465d304bd9acf6085897db40 Mon Sep 17 00:00:00 2001 From: zaharovadasha Date: Mon, 4 Jun 2018 20:31:22 +0300 Subject: [PATCH 5/7] itog --- ZaharovaDD/lab2/gtest/gtest-all.cc | 9592 ++++++++ ZaharovaDD/lab2/gtest/gtest.h | 20063 ++++++++++++++++ ZaharovaDD/lab2/include/list.h | 170 + ZaharovaDD/lab2/include/monom.h | 20 + ZaharovaDD/lab2/include/node.h | 16 + ZaharovaDD/lab2/include/polynom.h | 33 + ZaharovaDD/lab2/include/table.h | 64 + ZaharovaDD/lab2/include/tableHash.h | 155 + ZaharovaDD/lab2/include/tableOrder.h | 94 + ZaharovaDD/lab2/include/tableUnorder.h | 82 + ZaharovaDD/lab2/otchet_table.docx | Bin 0 -> 124816 bytes ZaharovaDD/lab2/samples/main_table.cpp | 109 + ZaharovaDD/lab2/sln/table/gtest/gtest.vcxproj | 138 + .../sln/table/gtest/gtest.vcxproj.filters | 23 + .../lab2/sln/table/samples/samples.vcxproj | 162 + .../sln/table/samples/samples.vcxproj.filters | 14 + ZaharovaDD/lab2/sln/table/table.sln | 65 + ZaharovaDD/lab2/sln/table/table/table.vcxproj | 192 + .../sln/table/table/table.vcxproj.filters | 65 + ZaharovaDD/lab2/sln/table/test/test.vcxproj | 165 + .../lab2/sln/table/test/test.vcxproj.filters | 23 + ZaharovaDD/lab2/src/list.cpp | 1 + ZaharovaDD/lab2/src/monom.cpp | 1 + ZaharovaDD/lab2/src/node.cpp | 1 + ZaharovaDD/lab2/src/polynom.cpp | 231 + ZaharovaDD/lab2/src/table.cpp | 1 + ZaharovaDD/lab2/src/tableHash.cpp | 1 + ZaharovaDD/lab2/src/tableOrder.cpp | 1 + ZaharovaDD/lab2/src/tableUnorder.cpp | 1 + ZaharovaDD/lab2/test/test_list.cpp | 136 + ZaharovaDD/lab2/test/test_main.cpp | 5 + ZaharovaDD/lab2/test/test_polynom.cpp | 146 + ZaharovaDD/lab2/test/test_table.cpp | 197 + 33 files changed, 31967 insertions(+) create mode 100644 ZaharovaDD/lab2/gtest/gtest-all.cc create mode 100644 ZaharovaDD/lab2/gtest/gtest.h create mode 100644 ZaharovaDD/lab2/include/list.h create mode 100644 ZaharovaDD/lab2/include/monom.h create mode 100644 ZaharovaDD/lab2/include/node.h create mode 100644 ZaharovaDD/lab2/include/polynom.h create mode 100644 ZaharovaDD/lab2/include/table.h create mode 100644 ZaharovaDD/lab2/include/tableHash.h create mode 100644 ZaharovaDD/lab2/include/tableOrder.h create mode 100644 ZaharovaDD/lab2/include/tableUnorder.h create mode 100644 ZaharovaDD/lab2/otchet_table.docx create mode 100644 ZaharovaDD/lab2/samples/main_table.cpp create mode 100644 ZaharovaDD/lab2/sln/table/gtest/gtest.vcxproj create mode 100644 ZaharovaDD/lab2/sln/table/gtest/gtest.vcxproj.filters create mode 100644 ZaharovaDD/lab2/sln/table/samples/samples.vcxproj create mode 100644 ZaharovaDD/lab2/sln/table/samples/samples.vcxproj.filters create mode 100644 ZaharovaDD/lab2/sln/table/table.sln create mode 100644 ZaharovaDD/lab2/sln/table/table/table.vcxproj create mode 100644 ZaharovaDD/lab2/sln/table/table/table.vcxproj.filters create mode 100644 ZaharovaDD/lab2/sln/table/test/test.vcxproj create mode 100644 ZaharovaDD/lab2/sln/table/test/test.vcxproj.filters create mode 100644 ZaharovaDD/lab2/src/list.cpp create mode 100644 ZaharovaDD/lab2/src/monom.cpp create mode 100644 ZaharovaDD/lab2/src/node.cpp create mode 100644 ZaharovaDD/lab2/src/polynom.cpp create mode 100644 ZaharovaDD/lab2/src/table.cpp create mode 100644 ZaharovaDD/lab2/src/tableHash.cpp create mode 100644 ZaharovaDD/lab2/src/tableOrder.cpp create mode 100644 ZaharovaDD/lab2/src/tableUnorder.cpp create mode 100644 ZaharovaDD/lab2/test/test_list.cpp create mode 100644 ZaharovaDD/lab2/test/test_main.cpp create mode 100644 ZaharovaDD/lab2/test/test_polynom.cpp create mode 100644 ZaharovaDD/lab2/test/test_table.cpp diff --git a/ZaharovaDD/lab2/gtest/gtest-all.cc b/ZaharovaDD/lab2/gtest/gtest-all.cc new file mode 100644 index 000000000..ff9e51235 --- /dev/null +++ b/ZaharovaDD/lab2/gtest/gtest-all.cc @@ -0,0 +1,9592 @@ +// Copyright 2008, 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: mheule@google.com (Markus Heule) +// +// Google C++ Testing Framework (Google Test) +// +// Sometimes it's desirable to build Google Test by compiling a single file. +// This file serves this purpose. + +// This line ensures that gtest.h can be compiled on its own, even +// when it's fused. +#include "gtest.h" + +// The following lines pull in the real gtest *.cc files. +// 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 +// 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) +// +// The Google C++ Testing Framework (Google Test) + +// 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) +// +// Utilities for testing Google Test itself and code that uses Google Test +// (e.g. frameworks built on top of Google Test). + +#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_ +#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_ + + +namespace testing { + +// This helper class can be used to mock out Google Test failure reporting +// so that we can test Google Test or code that builds on Google Test. +// +// An object of this class appends a TestPartResult object to the +// TestPartResultArray object given in the constructor whenever a Google Test +// failure is reported. It can either intercept only failures that are +// generated in the same thread that created this object or it can intercept +// all generated failures. The scope of this mock object can be controlled with +// the second argument to the two arguments constructor. +class GTEST_API_ ScopedFakeTestPartResultReporter + : public TestPartResultReporterInterface { + public: + // The two possible mocking modes of this object. + enum InterceptMode { + INTERCEPT_ONLY_CURRENT_THREAD, // Intercepts only thread local failures. + INTERCEPT_ALL_THREADS // Intercepts all failures. + }; + + // The c'tor sets this object as the test part result reporter used + // by Google Test. The 'result' parameter specifies where to report the + // results. This reporter will only catch failures generated in the current + // thread. DEPRECATED + explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result); + + // Same as above, but you can choose the interception scope of this object. + ScopedFakeTestPartResultReporter(InterceptMode intercept_mode, + TestPartResultArray* result); + + // The d'tor restores the previous test part result reporter. + virtual ~ScopedFakeTestPartResultReporter(); + + // Appends the TestPartResult object to the TestPartResultArray + // received in the constructor. + // + // This method is from the TestPartResultReporterInterface + // interface. + virtual void ReportTestPartResult(const TestPartResult& result); + private: + void Init(); + + const InterceptMode intercept_mode_; + TestPartResultReporterInterface* old_reporter_; + TestPartResultArray* const result_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter); +}; + +namespace internal { + +// A helper class for implementing EXPECT_FATAL_FAILURE() and +// EXPECT_NONFATAL_FAILURE(). Its destructor verifies that the given +// TestPartResultArray contains exactly one failure that has the given +// type and contains the given substring. If that's not the case, a +// non-fatal failure will be generated. +class GTEST_API_ SingleFailureChecker { + public: + // The constructor remembers the arguments. + SingleFailureChecker(const TestPartResultArray* results, + TestPartResult::Type type, + const string& substr); + ~SingleFailureChecker(); + private: + const TestPartResultArray* const results_; + const TestPartResult::Type type_; + const string substr_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker); +}; + +} // namespace internal + +} // namespace testing + +// A set of macros for testing Google Test assertions or code that's expected +// to generate Google Test fatal failures. It verifies that the given +// statement will cause exactly one fatal Google Test failure with 'substr' +// being part of the failure message. +// +// There are two different versions of this macro. EXPECT_FATAL_FAILURE only +// affects and considers failures generated in the current thread and +// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. +// +// The verification of the assertion is done correctly even when the statement +// throws an exception or aborts the current function. +// +// Known restrictions: +// - 'statement' cannot reference local non-static variables or +// non-static members of the current object. +// - 'statement' cannot return a value. +// - You cannot stream a failure message to this macro. +// +// Note that even though the implementations of the following two +// macros are much alike, we cannot refactor them to use a common +// helper macro, due to some peculiarity in how the preprocessor +// works. The AcceptsMacroThatExpandsToUnprotectedComma test in +// gtest_unittest.cc will fail to compile if we do that. +#define EXPECT_FATAL_FAILURE(statement, substr) \ + do { \ + class GTestExpectFatalFailureHelper {\ + public:\ + static void Execute() { statement; }\ + };\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter:: \ + INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ + GTestExpectFatalFailureHelper::Execute();\ + }\ + } while (::testing::internal::AlwaysFalse()) + +#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ + do { \ + class GTestExpectFatalFailureHelper {\ + public:\ + static void Execute() { statement; }\ + };\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter:: \ + INTERCEPT_ALL_THREADS, >est_failures);\ + GTestExpectFatalFailureHelper::Execute();\ + }\ + } while (::testing::internal::AlwaysFalse()) + +// A macro for testing Google Test assertions or code that's expected to +// generate Google Test non-fatal failures. It asserts that the given +// statement will cause exactly one non-fatal Google Test failure with 'substr' +// being part of the failure message. +// +// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only +// affects and considers failures generated in the current thread and +// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. +// +// 'statement' is allowed to reference local variables and members of +// the current object. +// +// The verification of the assertion is done correctly even when the statement +// throws an exception or aborts the current function. +// +// Known restrictions: +// - You cannot stream a failure message to this macro. +// +// Note that even though the implementations of the following two +// macros are much alike, we cannot refactor them to use a common +// helper macro, due to some peculiarity in how the preprocessor +// works. If we do that, the code won't compile when the user gives +// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that +// expands to code containing an unprotected comma. The +// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc +// catches that. +// +// For the same reason, we have to write +// if (::testing::internal::AlwaysTrue()) { statement; } +// instead of +// GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) +// to avoid an MSVC warning on unreachable code. +#define EXPECT_NONFATAL_FAILURE(statement, substr) \ + do {\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ + (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter:: \ + INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ + if (::testing::internal::AlwaysTrue()) { statement; }\ + }\ + } while (::testing::internal::AlwaysFalse()) + +#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ + do {\ + ::testing::TestPartResultArray gtest_failures;\ + ::testing::internal::SingleFailureChecker gtest_checker(\ + >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ + (substr));\ + {\ + ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ + ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \ + >est_failures);\ + if (::testing::internal::AlwaysTrue()) { statement; }\ + }\ + } while (::testing::internal::AlwaysFalse()) + +#endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include // NOLINT +#include +#include + +#if GTEST_OS_LINUX + +// TODO(kenton@google.com): Use autoconf to detect availability of +// gettimeofday(). +# define GTEST_HAS_GETTIMEOFDAY_ 1 + +# include // NOLINT +# include // NOLINT +# include // NOLINT +// Declares vsnprintf(). This header is not available on Windows. +# include // NOLINT +# include // NOLINT +# include // NOLINT +# include // NOLINT +# include + +#elif GTEST_OS_SYMBIAN +# define GTEST_HAS_GETTIMEOFDAY_ 1 +# include // NOLINT + +#elif GTEST_OS_ZOS +# define GTEST_HAS_GETTIMEOFDAY_ 1 +# include // NOLINT + +// On z/OS we additionally need strings.h for strcasecmp. +# include // NOLINT + +#elif GTEST_OS_WINDOWS_MOBILE // We are on Windows CE. + +# include // NOLINT + +#elif GTEST_OS_WINDOWS // We are on Windows proper. + +# include // NOLINT +# include // NOLINT +# include // NOLINT +# include // NOLINT + +# if GTEST_OS_WINDOWS_MINGW +// MinGW has gettimeofday() but not _ftime64(). +// TODO(kenton@google.com): Use autoconf to detect availability of +// gettimeofday(). +// TODO(kenton@google.com): There are other ways to get the time on +// Windows, like GetTickCount() or GetSystemTimeAsFileTime(). MinGW +// supports these. consider using them instead. +# define GTEST_HAS_GETTIMEOFDAY_ 1 +# include // NOLINT +# endif // GTEST_OS_WINDOWS_MINGW + +// cpplint thinks that the header is already included, so we want to +// silence it. +# include // NOLINT + +#else + +// Assume other platforms have gettimeofday(). +// TODO(kenton@google.com): Use autoconf to detect availability of +// gettimeofday(). +# define GTEST_HAS_GETTIMEOFDAY_ 1 + +// cpplint thinks that the header is already included, so we want to +// silence it. +# include // NOLINT +# include // NOLINT + +#endif // GTEST_OS_LINUX + +#if GTEST_HAS_EXCEPTIONS +# include +#endif + +#if GTEST_CAN_STREAM_RESULTS_ +# include // NOLINT +# include // NOLINT +#endif + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +// 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 +// 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. + +// Utility functions and classes used by the Google C++ testing framework. +// +// Author: wan@google.com (Zhanyong Wan) +// +// This file contains purely Google Test's internal implementation. Please +// DO NOT #INCLUDE IT IN A USER PROGRAM. + +#ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_ +#define GTEST_SRC_GTEST_INTERNAL_INL_H_ + +// GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is +// part of Google Test's implementation; otherwise it's undefined. +#if !GTEST_IMPLEMENTATION_ +// A user is trying to include this from his code - just say no. +# error "gtest-internal-inl.h is part of Google Test's internal implementation." +# error "It must not be included except by Google Test itself." +#endif // GTEST_IMPLEMENTATION_ + +#ifndef _WIN32_WCE +# include +#endif // !_WIN32_WCE +#include +#include // For strtoll/_strtoul64/malloc/free. +#include // For memmove. + +#include +#include +#include + + +#if GTEST_CAN_STREAM_RESULTS_ +# include // NOLINT +# include // NOLINT +#endif + +#if GTEST_OS_WINDOWS +# include // NOLINT +#endif // GTEST_OS_WINDOWS + + +namespace testing { + +// Declares the flags. +// +// We don't want the users to modify this flag in the code, but want +// Google Test's own unit tests to be able to access it. Therefore we +// declare it here as opposed to in gtest.h. +GTEST_DECLARE_bool_(death_test_use_fork); + +namespace internal { + +// The value of GetTestTypeId() as seen from within the Google Test +// library. This is solely for testing GetTestTypeId(). +GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest; + +// Names of the flags (needed for parsing Google Test flags). +const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests"; +const char kBreakOnFailureFlag[] = "break_on_failure"; +const char kCatchExceptionsFlag[] = "catch_exceptions"; +const char kColorFlag[] = "color"; +const char kFilterFlag[] = "filter"; +const char kListTestsFlag[] = "list_tests"; +const char kOutputFlag[] = "output"; +const char kPrintTimeFlag[] = "print_time"; +const char kRandomSeedFlag[] = "random_seed"; +const char kRepeatFlag[] = "repeat"; +const char kShuffleFlag[] = "shuffle"; +const char kStackTraceDepthFlag[] = "stack_trace_depth"; +const char kStreamResultToFlag[] = "stream_result_to"; +const char kThrowOnFailureFlag[] = "throw_on_failure"; + +// A valid random seed must be in [1, kMaxRandomSeed]. +const int kMaxRandomSeed = 99999; + +// g_help_flag is true iff the --help flag or an equivalent form is +// specified on the command line. +GTEST_API_ extern bool g_help_flag; + +// Returns the current time in milliseconds. +GTEST_API_ TimeInMillis GetTimeInMillis(); + +// Returns true iff Google Test should use colors in the output. +GTEST_API_ bool ShouldUseColor(bool stdout_is_tty); + +// Formats the given time in milliseconds as seconds. +GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms); + +// Converts the given time in milliseconds to a date string in the ISO 8601 +// format, without the timezone information. N.B.: due to the use the +// non-reentrant localtime() function, this function is not thread safe. Do +// not use it in any code that can be called from multiple threads. +GTEST_API_ std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms); + +// Parses a string for an Int32 flag, in the form of "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +GTEST_API_ bool ParseInt32Flag( + const char* str, const char* flag, Int32* value); + +// Returns a random seed in range [1, kMaxRandomSeed] based on the +// given --gtest_random_seed flag value. +inline int GetRandomSeedFromFlag(Int32 random_seed_flag) { + const unsigned int raw_seed = (random_seed_flag == 0) ? + static_cast(GetTimeInMillis()) : + static_cast(random_seed_flag); + + // Normalizes the actual seed to range [1, kMaxRandomSeed] such that + // it's easy to type. + const int normalized_seed = + static_cast((raw_seed - 1U) % + static_cast(kMaxRandomSeed)) + 1; + return normalized_seed; +} + +// Returns the first valid random seed after 'seed'. The behavior is +// undefined if 'seed' is invalid. The seed after kMaxRandomSeed is +// considered to be 1. +inline int GetNextRandomSeed(int seed) { + GTEST_CHECK_(1 <= seed && seed <= kMaxRandomSeed) + << "Invalid random seed " << seed << " - must be in [1, " + << kMaxRandomSeed << "]."; + const int next_seed = seed + 1; + return (next_seed > kMaxRandomSeed) ? 1 : next_seed; +} + +// This class saves the values of all Google Test flags in its c'tor, and +// restores them in its d'tor. +class GTestFlagSaver { + public: + // The c'tor. + GTestFlagSaver() { + also_run_disabled_tests_ = GTEST_FLAG(also_run_disabled_tests); + break_on_failure_ = GTEST_FLAG(break_on_failure); + catch_exceptions_ = GTEST_FLAG(catch_exceptions); + color_ = GTEST_FLAG(color); + death_test_style_ = GTEST_FLAG(death_test_style); + death_test_use_fork_ = GTEST_FLAG(death_test_use_fork); + filter_ = GTEST_FLAG(filter); + internal_run_death_test_ = GTEST_FLAG(internal_run_death_test); + list_tests_ = GTEST_FLAG(list_tests); + output_ = GTEST_FLAG(output); + print_time_ = GTEST_FLAG(print_time); + random_seed_ = GTEST_FLAG(random_seed); + repeat_ = GTEST_FLAG(repeat); + shuffle_ = GTEST_FLAG(shuffle); + stack_trace_depth_ = GTEST_FLAG(stack_trace_depth); + stream_result_to_ = GTEST_FLAG(stream_result_to); + throw_on_failure_ = GTEST_FLAG(throw_on_failure); + } + + // The d'tor is not virtual. DO NOT INHERIT FROM THIS CLASS. + ~GTestFlagSaver() { + GTEST_FLAG(also_run_disabled_tests) = also_run_disabled_tests_; + GTEST_FLAG(break_on_failure) = break_on_failure_; + GTEST_FLAG(catch_exceptions) = catch_exceptions_; + GTEST_FLAG(color) = color_; + GTEST_FLAG(death_test_style) = death_test_style_; + GTEST_FLAG(death_test_use_fork) = death_test_use_fork_; + GTEST_FLAG(filter) = filter_; + GTEST_FLAG(internal_run_death_test) = internal_run_death_test_; + GTEST_FLAG(list_tests) = list_tests_; + GTEST_FLAG(output) = output_; + GTEST_FLAG(print_time) = print_time_; + GTEST_FLAG(random_seed) = random_seed_; + GTEST_FLAG(repeat) = repeat_; + GTEST_FLAG(shuffle) = shuffle_; + GTEST_FLAG(stack_trace_depth) = stack_trace_depth_; + GTEST_FLAG(stream_result_to) = stream_result_to_; + GTEST_FLAG(throw_on_failure) = throw_on_failure_; + } + + private: + // Fields for saving the original values of flags. + bool also_run_disabled_tests_; + bool break_on_failure_; + bool catch_exceptions_; + std::string color_; + std::string death_test_style_; + bool death_test_use_fork_; + std::string filter_; + std::string internal_run_death_test_; + bool list_tests_; + std::string output_; + bool print_time_; + internal::Int32 random_seed_; + internal::Int32 repeat_; + bool shuffle_; + internal::Int32 stack_trace_depth_; + std::string stream_result_to_; + bool throw_on_failure_; +} GTEST_ATTRIBUTE_UNUSED_; + +// Converts a Unicode code point to a narrow string in UTF-8 encoding. +// code_point parameter is of type UInt32 because wchar_t may not be +// wide enough to contain a code point. +// If the code_point is not a valid Unicode code point +// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted +// to "(Invalid Unicode 0xXXXXXXXX)". +GTEST_API_ std::string CodePointToUtf8(UInt32 code_point); + +// Converts a wide string to a narrow string in UTF-8 encoding. +// The wide string is assumed to have the following encoding: +// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS) +// UTF-32 if sizeof(wchar_t) == 4 (on Linux) +// Parameter str points to a null-terminated wide string. +// Parameter num_chars may additionally limit the number +// of wchar_t characters processed. -1 is used when the entire string +// should be processed. +// If the string contains code points that are not valid Unicode code points +// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output +// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding +// and contains invalid UTF-16 surrogate pairs, values in those pairs +// will be encoded as individual Unicode characters from Basic Normal Plane. +GTEST_API_ std::string WideStringToUtf8(const wchar_t* str, int num_chars); + +// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file +// if the variable is present. If a file already exists at this location, this +// function will write over it. If the variable is present, but the file cannot +// be created, prints an error and exits. +void WriteToShardStatusFileIfNeeded(); + +// Checks whether sharding is enabled by examining the relevant +// environment variable values. If the variables are present, +// but inconsistent (e.g., shard_index >= total_shards), prints +// an error and exits. If in_subprocess_for_death_test, sharding is +// disabled because it must only be applied to the original test +// process. Otherwise, we could filter out death tests we intended to execute. +GTEST_API_ bool ShouldShard(const char* total_shards_str, + const char* shard_index_str, + bool in_subprocess_for_death_test); + +// Parses the environment variable var as an Int32. If it is unset, +// returns default_val. If it is not an Int32, prints an error and +// and aborts. +GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val); + +// Given the total number of shards, the shard index, and the test id, +// returns true iff the test should be run on this shard. The test id is +// some arbitrary but unique non-negative integer assigned to each test +// method. Assumes that 0 <= shard_index < total_shards. +GTEST_API_ bool ShouldRunTestOnShard( + int total_shards, int shard_index, int test_id); + +// STL container utilities. + +// Returns the number of elements in the given container that satisfy +// the given predicate. +template +inline int CountIf(const Container& c, Predicate predicate) { + // Implemented as an explicit loop since std::count_if() in libCstd on + // Solaris has a non-standard signature. + int count = 0; + for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) { + if (predicate(*it)) + ++count; + } + return count; +} + +// Applies a function/functor to each element in the container. +template +void ForEach(const Container& c, Functor functor) { + std::for_each(c.begin(), c.end(), functor); +} + +// Returns the i-th element of the vector, or default_value if i is not +// in range [0, v.size()). +template +inline E GetElementOr(const std::vector& v, int i, E default_value) { + return (i < 0 || i >= static_cast(v.size())) ? default_value : v[i]; +} + +// Performs an in-place shuffle of a range of the vector's elements. +// 'begin' and 'end' are element indices as an STL-style range; +// i.e. [begin, end) are shuffled, where 'end' == size() means to +// shuffle to the end of the vector. +template +void ShuffleRange(internal::Random* random, int begin, int end, + std::vector* v) { + const int size = static_cast(v->size()); + GTEST_CHECK_(0 <= begin && begin <= size) + << "Invalid shuffle range start " << begin << ": must be in range [0, " + << size << "]."; + GTEST_CHECK_(begin <= end && end <= size) + << "Invalid shuffle range finish " << end << ": must be in range [" + << begin << ", " << size << "]."; + + // Fisher-Yates shuffle, from + // http://en.wikipedia.org/wiki/Fisher-Yates_shuffle + for (int range_width = end - begin; range_width >= 2; range_width--) { + const int last_in_range = begin + range_width - 1; + const int selected = begin + random->Generate(range_width); + std::swap((*v)[selected], (*v)[last_in_range]); + } +} + +// Performs an in-place shuffle of the vector's elements. +template +inline void Shuffle(internal::Random* random, std::vector* v) { + ShuffleRange(random, 0, static_cast(v->size()), v); +} + +// A function for deleting an object. Handy for being used as a +// functor. +template +static void Delete(T* x) { + delete x; +} + +// A predicate that checks the key of a TestProperty against a known key. +// +// TestPropertyKeyIs is copyable. +class TestPropertyKeyIs { + public: + // Constructor. + // + // TestPropertyKeyIs has NO default constructor. + explicit TestPropertyKeyIs(const std::string& key) : key_(key) {} + + // Returns true iff the test name of test property matches on key_. + bool operator()(const TestProperty& test_property) const { + return test_property.key() == key_; + } + + private: + std::string key_; +}; + +// Class UnitTestOptions. +// +// This class contains functions for processing options the user +// specifies when running the tests. It has only static members. +// +// In most cases, the user can specify an option using either an +// environment variable or a command line flag. E.g. you can set the +// test filter using either GTEST_FILTER or --gtest_filter. If both +// the variable and the flag are present, the latter overrides the +// former. +class GTEST_API_ UnitTestOptions { + public: + // Functions for processing the gtest_output flag. + + // Returns the output format, or "" for normal printed output. + static std::string GetOutputFormat(); + + // Returns the absolute path of the requested output file, or the + // default (test_detail.xml in the original working directory) if + // none was explicitly specified. + static std::string GetAbsolutePathToOutputFile(); + + // Functions for processing the gtest_filter flag. + + // Returns true iff the wildcard pattern matches the string. The + // first ':' or '\0' character in pattern marks the end of it. + // + // This recursive algorithm isn't very efficient, but is clear and + // works well enough for matching test names, which are short. + static bool PatternMatchesString(const char *pattern, const char *str); + + // Returns true iff the user-specified filter matches the test case + // name and the test name. + static bool FilterMatchesTest(const std::string &test_case_name, + const std::string &test_name); + +#if GTEST_OS_WINDOWS + // Function for supporting the gtest_catch_exception flag. + + // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the + // given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise. + // This function is useful as an __except condition. + static int GTestShouldProcessSEH(DWORD exception_code); +#endif // GTEST_OS_WINDOWS + + // Returns true if "name" matches the ':' separated list of glob-style + // filters in "filter". + static bool MatchesFilter(const std::string& name, const char* filter); +}; + +// Returns the current application's name, removing directory path if that +// is present. Used by UnitTestOptions::GetOutputFile. +GTEST_API_ FilePath GetCurrentExecutableName(); + +// The role interface for getting the OS stack trace as a string. +class OsStackTraceGetterInterface { + public: + OsStackTraceGetterInterface() {} + virtual ~OsStackTraceGetterInterface() {} + + // Returns the current OS stack trace as an std::string. Parameters: + // + // max_depth - the maximum number of stack frames to be included + // in the trace. + // skip_count - the number of top frames to be skipped; doesn't count + // against max_depth. + virtual string CurrentStackTrace(int max_depth, int skip_count) = 0; + + // UponLeavingGTest() should be called immediately before Google Test calls + // user code. It saves some information about the current stack that + // CurrentStackTrace() will use to find and hide Google Test stack frames. + virtual void UponLeavingGTest() = 0; + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface); +}; + +// A working implementation of the OsStackTraceGetterInterface interface. +class OsStackTraceGetter : public OsStackTraceGetterInterface { + public: + OsStackTraceGetter() : caller_frame_(NULL) {} + + virtual string CurrentStackTrace(int max_depth, int skip_count) + GTEST_LOCK_EXCLUDED_(mutex_); + + virtual void UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_); + + // This string is inserted in place of stack frames that are part of + // Google Test's implementation. + static const char* const kElidedFramesMarker; + + private: + Mutex mutex_; // protects all internal state + + // We save the stack frame below the frame that calls user code. + // We do this because the address of the frame immediately below + // the user code changes between the call to UponLeavingGTest() + // and any calls to CurrentStackTrace() from within the user code. + void* caller_frame_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter); +}; + +// Information about a Google Test trace point. +struct TraceInfo { + const char* file; + int line; + std::string message; +}; + +// This is the default global test part result reporter used in UnitTestImpl. +// This class should only be used by UnitTestImpl. +class DefaultGlobalTestPartResultReporter + : public TestPartResultReporterInterface { + public: + explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test); + // Implements the TestPartResultReporterInterface. Reports the test part + // result in the current test. + virtual void ReportTestPartResult(const TestPartResult& result); + + private: + UnitTestImpl* const unit_test_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultGlobalTestPartResultReporter); +}; + +// This is the default per thread test part result reporter used in +// UnitTestImpl. This class should only be used by UnitTestImpl. +class DefaultPerThreadTestPartResultReporter + : public TestPartResultReporterInterface { + public: + explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test); + // Implements the TestPartResultReporterInterface. The implementation just + // delegates to the current global test part result reporter of *unit_test_. + virtual void ReportTestPartResult(const TestPartResult& result); + + private: + UnitTestImpl* const unit_test_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultPerThreadTestPartResultReporter); +}; + +// The private implementation of the UnitTest class. We don't protect +// the methods under a mutex, as this class is not accessible by a +// user and the UnitTest class that delegates work to this class does +// proper locking. +class GTEST_API_ UnitTestImpl { + public: + explicit UnitTestImpl(UnitTest* parent); + virtual ~UnitTestImpl(); + + // There are two different ways to register your own TestPartResultReporter. + // You can register your own repoter to listen either only for test results + // from the current thread or for results from all threads. + // By default, each per-thread test result repoter just passes a new + // TestPartResult to the global test result reporter, which registers the + // test part result for the currently running test. + + // Returns the global test part result reporter. + TestPartResultReporterInterface* GetGlobalTestPartResultReporter(); + + // Sets the global test part result reporter. + void SetGlobalTestPartResultReporter( + TestPartResultReporterInterface* reporter); + + // Returns the test part result reporter for the current thread. + TestPartResultReporterInterface* GetTestPartResultReporterForCurrentThread(); + + // Sets the test part result reporter for the current thread. + void SetTestPartResultReporterForCurrentThread( + TestPartResultReporterInterface* reporter); + + // Gets the number of successful test cases. + int successful_test_case_count() const; + + // Gets the number of failed test cases. + int failed_test_case_count() const; + + // Gets the number of all test cases. + int total_test_case_count() const; + + // Gets the number of all test cases that contain at least one test + // that should run. + int test_case_to_run_count() const; + + // Gets the number of successful tests. + int successful_test_count() const; + + // Gets the number of failed tests. + int failed_test_count() const; + + // Gets the number of disabled tests that will be reported in the XML report. + int reportable_disabled_test_count() const; + + // Gets the number of disabled tests. + int disabled_test_count() const; + + // Gets the number of tests to be printed in the XML report. + int reportable_test_count() const; + + // Gets the number of all tests. + int total_test_count() const; + + // Gets the number of tests that should run. + int test_to_run_count() const; + + // Gets the time of the test program start, in ms from the start of the + // UNIX epoch. + TimeInMillis start_timestamp() const { return start_timestamp_; } + + // Gets the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns true iff the unit test passed (i.e. all test cases passed). + bool Passed() const { return !Failed(); } + + // Returns true iff the unit test failed (i.e. some test case failed + // or something outside of all tests failed). + bool Failed() const { + return failed_test_case_count() > 0 || ad_hoc_test_result()->Failed(); + } + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + const TestCase* GetTestCase(int i) const { + const int index = GetElementOr(test_case_indices_, i, -1); + return index < 0 ? NULL : test_cases_[i]; + } + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + TestCase* GetMutableTestCase(int i) { + const int index = GetElementOr(test_case_indices_, i, -1); + return index < 0 ? NULL : test_cases_[index]; + } + + // Provides access to the event listener list. + TestEventListeners* listeners() { return &listeners_; } + + // Returns the TestResult for the test that's currently running, or + // the TestResult for the ad hoc test if no test is running. + TestResult* current_test_result(); + + // Returns the TestResult for the ad hoc test. + const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; } + + // Sets the OS stack trace getter. + // + // Does nothing if the input and the current OS stack trace getter + // are the same; otherwise, deletes the old getter and makes the + // input the current getter. + void set_os_stack_trace_getter(OsStackTraceGetterInterface* getter); + + // Returns the current OS stack trace getter if it is not NULL; + // otherwise, creates an OsStackTraceGetter, makes it the current + // getter, and returns it. + OsStackTraceGetterInterface* os_stack_trace_getter(); + + // Returns the current OS stack trace as an std::string. + // + // The maximum number of stack frames to be included is specified by + // the gtest_stack_trace_depth flag. The skip_count parameter + // specifies the number of top frames to be skipped, which doesn't + // count against the number of frames to be included. + // + // For example, if Foo() calls Bar(), which in turn calls + // CurrentOsStackTraceExceptTop(1), Foo() will be included in the + // trace but Bar() and CurrentOsStackTraceExceptTop() won't. + std::string CurrentOsStackTraceExceptTop(int skip_count) GTEST_NO_INLINE_; + + // Finds and returns a TestCase with the given name. If one doesn't + // exist, creates one and returns it. + // + // Arguments: + // + // test_case_name: name of the test case + // type_param: the name of the test's type parameter, or NULL if + // this is not a typed or a type-parameterized test. + // set_up_tc: pointer to the function that sets up the test case + // tear_down_tc: pointer to the function that tears down the test case + TestCase* GetTestCase(const char* test_case_name, + const char* type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc); + + // Adds a TestInfo to the unit test. + // + // Arguments: + // + // set_up_tc: pointer to the function that sets up the test case + // tear_down_tc: pointer to the function that tears down the test case + // test_info: the TestInfo object + void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc, + TestInfo* test_info) { + // In order to support thread-safe death tests, we need to + // remember the original working directory when the test program + // was first invoked. We cannot do this in RUN_ALL_TESTS(), as + // the user may have changed the current directory before calling + // RUN_ALL_TESTS(). Therefore we capture the current directory in + // AddTestInfo(), which is called to register a TEST or TEST_F + // before main() is reached. + if (original_working_dir_.IsEmpty()) { + original_working_dir_.Set(FilePath::GetCurrentDir()); + GTEST_CHECK_(!original_working_dir_.IsEmpty()) + << "Failed to get the current working directory."; + } + + GetTestCase(test_info->test_case_name(), + test_info->type_param(), + set_up_tc, + tear_down_tc)->AddTestInfo(test_info); + } + +#if GTEST_HAS_PARAM_TEST + // Returns ParameterizedTestCaseRegistry object used to keep track of + // value-parameterized tests and instantiate and register them. + internal::ParameterizedTestCaseRegistry& parameterized_test_registry() { + return parameterized_test_registry_; + } +#endif // GTEST_HAS_PARAM_TEST + + // Sets the TestCase object for the test that's currently running. + void set_current_test_case(TestCase* a_current_test_case) { + current_test_case_ = a_current_test_case; + } + + // Sets the TestInfo object for the test that's currently running. If + // current_test_info is NULL, the assertion results will be stored in + // ad_hoc_test_result_. + void set_current_test_info(TestInfo* a_current_test_info) { + current_test_info_ = a_current_test_info; + } + + // Registers all parameterized tests defined using TEST_P and + // INSTANTIATE_TEST_CASE_P, creating regular tests for each test/parameter + // combination. This method can be called more then once; it has guards + // protecting from registering the tests more then once. If + // value-parameterized tests are disabled, RegisterParameterizedTests is + // present but does nothing. + void RegisterParameterizedTests(); + + // Runs all tests in this UnitTest object, prints the result, and + // returns true if all tests are successful. If any exception is + // thrown during a test, this test is considered to be failed, but + // the rest of the tests will still be run. + bool RunAllTests(); + + // Clears the results of all tests, except the ad hoc tests. + void ClearNonAdHocTestResult() { + ForEach(test_cases_, TestCase::ClearTestCaseResult); + } + + // Clears the results of ad-hoc test assertions. + void ClearAdHocTestResult() { + ad_hoc_test_result_.Clear(); + } + + // Adds a TestProperty to the current TestResult object when invoked in a + // context of a test or a test case, or to the global property set. If the + // result already contains a property with the same key, the value will be + // updated. + void RecordProperty(const TestProperty& test_property); + + enum ReactionToSharding { + HONOR_SHARDING_PROTOCOL, + IGNORE_SHARDING_PROTOCOL + }; + + // Matches the full name of each test against the user-specified + // filter to decide whether the test should run, then records the + // result in each TestCase and TestInfo object. + // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests + // based on sharding variables in the environment. + // Returns the number of tests that should run. + int FilterTests(ReactionToSharding shard_tests); + + // Prints the names of the tests matching the user-specified filter flag. + void ListTestsMatchingFilter(); + + const TestCase* current_test_case() const { return current_test_case_; } + TestInfo* current_test_info() { return current_test_info_; } + const TestInfo* current_test_info() const { return current_test_info_; } + + // Returns the vector of environments that need to be set-up/torn-down + // before/after the tests are run. + std::vector& environments() { return environments_; } + + // Getters for the per-thread Google Test trace stack. + std::vector& gtest_trace_stack() { + return *(gtest_trace_stack_.pointer()); + } + const std::vector& gtest_trace_stack() const { + return gtest_trace_stack_.get(); + } + +#if GTEST_HAS_DEATH_TEST + void InitDeathTestSubprocessControlInfo() { + internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag()); + } + // Returns a pointer to the parsed --gtest_internal_run_death_test + // flag, or NULL if that flag was not specified. + // This information is useful only in a death test child process. + // Must not be called before a call to InitGoogleTest. + const InternalRunDeathTestFlag* internal_run_death_test_flag() const { + return internal_run_death_test_flag_.get(); + } + + // Returns a pointer to the current death test factory. + internal::DeathTestFactory* death_test_factory() { + return death_test_factory_.get(); + } + + void SuppressTestEventsIfInSubprocess(); + + friend class ReplaceDeathTestFactory; +#endif // GTEST_HAS_DEATH_TEST + + // Initializes the event listener performing XML output as specified by + // UnitTestOptions. Must not be called before InitGoogleTest. + void ConfigureXmlOutput(); + +#if GTEST_CAN_STREAM_RESULTS_ + // Initializes the event listener for streaming test results to a socket. + // Must not be called before InitGoogleTest. + void ConfigureStreamingOutput(); +#endif + + // Performs initialization dependent upon flag values obtained in + // ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to + // ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest + // this function is also called from RunAllTests. Since this function can be + // called more than once, it has to be idempotent. + void PostFlagParsingInit(); + + // Gets the random seed used at the start of the current test iteration. + int random_seed() const { return random_seed_; } + + // Gets the random number generator. + internal::Random* random() { return &random_; } + + // Shuffles all test cases, and the tests within each test case, + // making sure that death tests are still run first. + void ShuffleTests(); + + // Restores the test cases and tests to their order before the first shuffle. + void UnshuffleTests(); + + // Returns the value of GTEST_FLAG(catch_exceptions) at the moment + // UnitTest::Run() starts. + bool catch_exceptions() const { return catch_exceptions_; } + + private: + friend class ::testing::UnitTest; + + // Used by UnitTest::Run() to capture the state of + // GTEST_FLAG(catch_exceptions) at the moment it starts. + void set_catch_exceptions(bool value) { catch_exceptions_ = value; } + + // The UnitTest object that owns this implementation object. + UnitTest* const parent_; + + // The working directory when the first TEST() or TEST_F() was + // executed. + internal::FilePath original_working_dir_; + + // The default test part result reporters. + DefaultGlobalTestPartResultReporter default_global_test_part_result_reporter_; + DefaultPerThreadTestPartResultReporter + default_per_thread_test_part_result_reporter_; + + // Points to (but doesn't own) the global test part result reporter. + TestPartResultReporterInterface* global_test_part_result_repoter_; + + // Protects read and write access to global_test_part_result_reporter_. + internal::Mutex global_test_part_result_reporter_mutex_; + + // Points to (but doesn't own) the per-thread test part result reporter. + internal::ThreadLocal + per_thread_test_part_result_reporter_; + + // The vector of environments that need to be set-up/torn-down + // before/after the tests are run. + std::vector environments_; + + // The vector of TestCases in their original order. It owns the + // elements in the vector. + std::vector test_cases_; + + // Provides a level of indirection for the test case list to allow + // easy shuffling and restoring the test case order. The i-th + // element of this vector is the index of the i-th test case in the + // shuffled order. + std::vector test_case_indices_; + +#if GTEST_HAS_PARAM_TEST + // ParameterizedTestRegistry object used to register value-parameterized + // tests. + internal::ParameterizedTestCaseRegistry parameterized_test_registry_; + + // Indicates whether RegisterParameterizedTests() has been called already. + bool parameterized_tests_registered_; +#endif // GTEST_HAS_PARAM_TEST + + // Index of the last death test case registered. Initially -1. + int last_death_test_case_; + + // This points to the TestCase for the currently running test. It + // changes as Google Test goes through one test case after another. + // When no test is running, this is set to NULL and Google Test + // stores assertion results in ad_hoc_test_result_. Initially NULL. + TestCase* current_test_case_; + + // This points to the TestInfo for the currently running test. It + // changes as Google Test goes through one test after another. When + // no test is running, this is set to NULL and Google Test stores + // assertion results in ad_hoc_test_result_. Initially NULL. + TestInfo* current_test_info_; + + // Normally, a user only writes assertions inside a TEST or TEST_F, + // or inside a function called by a TEST or TEST_F. Since Google + // Test keeps track of which test is current running, it can + // associate such an assertion with the test it belongs to. + // + // If an assertion is encountered when no TEST or TEST_F is running, + // Google Test attributes the assertion result to an imaginary "ad hoc" + // test, and records the result in ad_hoc_test_result_. + TestResult ad_hoc_test_result_; + + // The list of event listeners that can be used to track events inside + // Google Test. + TestEventListeners listeners_; + + // The OS stack trace getter. Will be deleted when the UnitTest + // object is destructed. By default, an OsStackTraceGetter is used, + // but the user can set this field to use a custom getter if that is + // desired. + OsStackTraceGetterInterface* os_stack_trace_getter_; + + // True iff PostFlagParsingInit() has been called. + bool post_flag_parse_init_performed_; + + // The random number seed used at the beginning of the test run. + int random_seed_; + + // Our random number generator. + internal::Random random_; + + // The time of the test program start, in ms from the start of the + // UNIX epoch. + TimeInMillis start_timestamp_; + + // How long the test took to run, in milliseconds. + TimeInMillis elapsed_time_; + +#if GTEST_HAS_DEATH_TEST + // The decomposed components of the gtest_internal_run_death_test flag, + // parsed when RUN_ALL_TESTS is called. + internal::scoped_ptr internal_run_death_test_flag_; + internal::scoped_ptr death_test_factory_; +#endif // GTEST_HAS_DEATH_TEST + + // A per-thread stack of traces created by the SCOPED_TRACE() macro. + internal::ThreadLocal > gtest_trace_stack_; + + // The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests() + // starts. + bool catch_exceptions_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl); +}; // class UnitTestImpl + +// Convenience function for accessing the global UnitTest +// implementation object. +inline UnitTestImpl* GetUnitTestImpl() { + return UnitTest::GetInstance()->impl(); +} + +#if GTEST_USES_SIMPLE_RE + +// Internal helper functions for implementing the simple regular +// expression matcher. +GTEST_API_ bool IsInSet(char ch, const char* str); +GTEST_API_ bool IsAsciiDigit(char ch); +GTEST_API_ bool IsAsciiPunct(char ch); +GTEST_API_ bool IsRepeat(char ch); +GTEST_API_ bool IsAsciiWhiteSpace(char ch); +GTEST_API_ bool IsAsciiWordChar(char ch); +GTEST_API_ bool IsValidEscape(char ch); +GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch); +GTEST_API_ bool ValidateRegex(const char* regex); +GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str); +GTEST_API_ bool MatchRepetitionAndRegexAtHead( + bool escaped, char ch, char repeat, const char* regex, const char* str); +GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str); + +#endif // GTEST_USES_SIMPLE_RE + +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. +GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv); +GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv); + +#if GTEST_HAS_DEATH_TEST + +// Returns the message describing the last system error, regardless of the +// platform. +GTEST_API_ std::string GetLastErrnoDescription(); + +# if GTEST_OS_WINDOWS +// Provides leak-safe Windows kernel handle ownership. +class AutoHandle { + public: + AutoHandle() : handle_(INVALID_HANDLE_VALUE) {} + explicit AutoHandle(HANDLE handle) : handle_(handle) {} + + ~AutoHandle() { Reset(); } + + HANDLE Get() const { return handle_; } + void Reset() { Reset(INVALID_HANDLE_VALUE); } + void Reset(HANDLE handle) { + if (handle != handle_) { + if (handle_ != INVALID_HANDLE_VALUE) + ::CloseHandle(handle_); + handle_ = handle; + } + } + + private: + HANDLE handle_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle); +}; +# endif // GTEST_OS_WINDOWS + +// Attempts to parse a string into a positive integer pointed to by the +// number parameter. Returns true if that is possible. +// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use +// it here. +template +bool ParseNaturalNumber(const ::std::string& str, Integer* number) { + // Fail fast if the given string does not begin with a digit; + // this bypasses strtoXXX's "optional leading whitespace and plus + // or minus sign" semantics, which are undesirable here. + if (str.empty() || !IsDigit(str[0])) { + return false; + } + errno = 0; + + char* end; + // BiggestConvertible is the largest integer type that system-provided + // string-to-number conversion routines can return. + +# if GTEST_OS_WINDOWS && !defined(__GNUC__) + + // MSVC and C++ Builder define __int64 instead of the standard long long. + typedef unsigned __int64 BiggestConvertible; + const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10); + +# else + + typedef unsigned long long BiggestConvertible; // NOLINT + const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10); + +# endif // GTEST_OS_WINDOWS && !defined(__GNUC__) + + const bool parse_success = *end == '\0' && errno == 0; + + // TODO(vladl@google.com): Convert this to compile time assertion when it is + // available. + GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed)); + + const Integer result = static_cast(parsed); + if (parse_success && static_cast(result) == parsed) { + *number = result; + return true; + } + return false; +} +#endif // GTEST_HAS_DEATH_TEST + +// TestResult contains some private methods that should be hidden from +// Google Test user but are required for testing. This class allow our tests +// to access them. +// +// This class is supplied only for the purpose of testing Google Test's own +// constructs. Do not use it in user tests, either directly or indirectly. +class TestResultAccessor { + public: + static void RecordProperty(TestResult* test_result, + const std::string& xml_element, + const TestProperty& property) { + test_result->RecordProperty(xml_element, property); + } + + static void ClearTestPartResults(TestResult* test_result) { + test_result->ClearTestPartResults(); + } + + static const std::vector& test_part_results( + const TestResult& test_result) { + return test_result.test_part_results(); + } +}; + +#if GTEST_CAN_STREAM_RESULTS_ + +// Streams test results to the given port on the given host machine. +class StreamingListener : public EmptyTestEventListener { + public: + // Abstract base class for writing strings to a socket. + class AbstractSocketWriter { + public: + virtual ~AbstractSocketWriter() {} + + // Sends a string to the socket. + virtual void Send(const string& message) = 0; + + // Closes the socket. + virtual void CloseConnection() {} + + // Sends a string and a newline to the socket. + void SendLn(const string& message) { + Send(message + "\n"); + } + }; + + // Concrete class for actually writing strings to a socket. + class SocketWriter : public AbstractSocketWriter { + public: + SocketWriter(const string& host, const string& port) + : sockfd_(-1), host_name_(host), port_num_(port) { + MakeConnection(); + } + + virtual ~SocketWriter() { + if (sockfd_ != -1) + CloseConnection(); + } + + // Sends a string to the socket. + virtual void Send(const string& message) { + GTEST_CHECK_(sockfd_ != -1) + << "Send() can be called only when there is a connection."; + + const int len = static_cast(message.length()); + if (write(sockfd_, message.c_str(), len) != len) { + GTEST_LOG_(WARNING) + << "stream_result_to: failed to stream to " + << host_name_ << ":" << port_num_; + } + } + + private: + // Creates a client socket and connects to the server. + void MakeConnection(); + + // Closes the socket. + void CloseConnection() { + GTEST_CHECK_(sockfd_ != -1) + << "CloseConnection() can be called only when there is a connection."; + + close(sockfd_); + sockfd_ = -1; + } + + int sockfd_; // socket file descriptor + const string host_name_; + const string port_num_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(SocketWriter); + }; // class SocketWriter + + // Escapes '=', '&', '%', and '\n' characters in str as "%xx". + static string UrlEncode(const char* str); + + StreamingListener(const string& host, const string& port) + : socket_writer_(new SocketWriter(host, port)) { Start(); } + + explicit StreamingListener(AbstractSocketWriter* socket_writer) + : socket_writer_(socket_writer) { Start(); } + + void OnTestProgramStart(const UnitTest& /* unit_test */) { + SendLn("event=TestProgramStart"); + } + + void OnTestProgramEnd(const UnitTest& unit_test) { + // Note that Google Test current only report elapsed time for each + // test iteration, not for the entire test program. + SendLn("event=TestProgramEnd&passed=" + FormatBool(unit_test.Passed())); + + // Notify the streaming server to stop. + socket_writer_->CloseConnection(); + } + + void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) { + SendLn("event=TestIterationStart&iteration=" + + StreamableToString(iteration)); + } + + void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) { + SendLn("event=TestIterationEnd&passed=" + + FormatBool(unit_test.Passed()) + "&elapsed_time=" + + StreamableToString(unit_test.elapsed_time()) + "ms"); + } + + void OnTestCaseStart(const TestCase& test_case) { + SendLn(std::string("event=TestCaseStart&name=") + test_case.name()); + } + + void OnTestCaseEnd(const TestCase& test_case) { + SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed()) + + "&elapsed_time=" + StreamableToString(test_case.elapsed_time()) + + "ms"); + } + + void OnTestStart(const TestInfo& test_info) { + SendLn(std::string("event=TestStart&name=") + test_info.name()); + } + + void OnTestEnd(const TestInfo& test_info) { + SendLn("event=TestEnd&passed=" + + FormatBool((test_info.result())->Passed()) + + "&elapsed_time=" + + StreamableToString((test_info.result())->elapsed_time()) + "ms"); + } + + void OnTestPartResult(const TestPartResult& test_part_result) { + const char* file_name = test_part_result.file_name(); + if (file_name == NULL) + file_name = ""; + SendLn("event=TestPartResult&file=" + UrlEncode(file_name) + + "&line=" + StreamableToString(test_part_result.line_number()) + + "&message=" + UrlEncode(test_part_result.message())); + } + + private: + // Sends the given message and a newline to the socket. + void SendLn(const string& message) { socket_writer_->SendLn(message); } + + // Called at the start of streaming to notify the receiver what + // protocol we are using. + void Start() { SendLn("gtest_streaming_protocol_version=1.0"); } + + string FormatBool(bool value) { return value ? "1" : "0"; } + + const scoped_ptr socket_writer_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener); +}; // class StreamingListener + +#endif // GTEST_CAN_STREAM_RESULTS_ + +} // namespace internal +} // namespace testing + +#endif // GTEST_SRC_GTEST_INTERNAL_INL_H_ +#undef GTEST_IMPLEMENTATION_ + +#if GTEST_OS_WINDOWS +# define vsnprintf _vsnprintf +#endif // GTEST_OS_WINDOWS + +namespace testing { + +using internal::CountIf; +using internal::ForEach; +using internal::GetElementOr; +using internal::Shuffle; + +// Constants. + +// A test whose test case name or test name matches this filter is +// disabled and not run. +static const char kDisableTestFilter[] = "DISABLED_*:*/DISABLED_*"; + +// A test case whose name matches this filter is considered a death +// test case and will be run before test cases whose name doesn't +// match this filter. +static const char kDeathTestCaseFilter[] = "*DeathTest:*DeathTest/*"; + +// A test filter that matches everything. +static const char kUniversalFilter[] = "*"; + +// The default output file for XML output. +static const char kDefaultOutputFile[] = "test_detail.xml"; + +// The environment variable name for the test shard index. +static const char kTestShardIndex[] = "GTEST_SHARD_INDEX"; +// The environment variable name for the total number of test shards. +static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS"; +// The environment variable name for the test shard status file. +static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE"; + +namespace internal { + +// The text used in failure messages to indicate the start of the +// stack trace. +const char kStackTraceMarker[] = "\nStack trace:\n"; + +// g_help_flag is true iff the --help flag or an equivalent form is +// specified on the command line. +bool g_help_flag = false; + +} // namespace internal + +static const char* GetDefaultFilter() { + return kUniversalFilter; +} + +GTEST_DEFINE_bool_( + also_run_disabled_tests, + internal::BoolFromGTestEnv("also_run_disabled_tests", false), + "Run disabled tests too, in addition to the tests normally being run."); + +GTEST_DEFINE_bool_( + break_on_failure, + internal::BoolFromGTestEnv("break_on_failure", false), + "True iff a failed assertion should be a debugger break-point."); + +GTEST_DEFINE_bool_( + catch_exceptions, + internal::BoolFromGTestEnv("catch_exceptions", true), + "True iff " GTEST_NAME_ + " should catch exceptions and treat them as test failures."); + +GTEST_DEFINE_string_( + color, + internal::StringFromGTestEnv("color", "auto"), + "Whether to use colors in the output. Valid values: yes, no, " + "and auto. 'auto' means to use colors if the output is " + "being sent to a terminal and the TERM environment variable " + "is set to a terminal type that supports colors."); + +GTEST_DEFINE_string_( + filter, + internal::StringFromGTestEnv("filter", GetDefaultFilter()), + "A colon-separated list of glob (not regex) patterns " + "for filtering the tests to run, optionally followed by a " + "'-' and a : separated list of negative patterns (tests to " + "exclude). A test is run if it matches one of the positive " + "patterns and does not match any of the negative patterns."); + +GTEST_DEFINE_bool_(list_tests, false, + "List all tests without running them."); + +GTEST_DEFINE_string_( + output, + internal::StringFromGTestEnv("output", ""), + "A format (currently must be \"xml\"), optionally followed " + "by a colon and an output file name or directory. A directory " + "is indicated by a trailing pathname separator. " + "Examples: \"xml:filename.xml\", \"xml::directoryname/\". " + "If a directory is specified, output files will be created " + "within that directory, with file-names based on the test " + "executable's name and, if necessary, made unique by adding " + "digits."); + +GTEST_DEFINE_bool_( + print_time, + internal::BoolFromGTestEnv("print_time", true), + "True iff " GTEST_NAME_ + " should display elapsed time in text output."); + +GTEST_DEFINE_int32_( + random_seed, + internal::Int32FromGTestEnv("random_seed", 0), + "Random number seed to use when shuffling test orders. Must be in range " + "[1, 99999], or 0 to use a seed based on the current time."); + +GTEST_DEFINE_int32_( + repeat, + internal::Int32FromGTestEnv("repeat", 1), + "How many times to repeat each test. Specify a negative number " + "for repeating forever. Useful for shaking out flaky tests."); + +GTEST_DEFINE_bool_( + show_internal_stack_frames, false, + "True iff " GTEST_NAME_ " should include internal stack frames when " + "printing test failure stack traces."); + +GTEST_DEFINE_bool_( + shuffle, + internal::BoolFromGTestEnv("shuffle", false), + "True iff " GTEST_NAME_ + " should randomize tests' order on every run."); + +GTEST_DEFINE_int32_( + stack_trace_depth, + internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth), + "The maximum number of stack frames to print when an " + "assertion fails. The valid range is 0 through 100, inclusive."); + +GTEST_DEFINE_string_( + stream_result_to, + internal::StringFromGTestEnv("stream_result_to", ""), + "This flag specifies the host name and the port number on which to stream " + "test results. Example: \"localhost:555\". The flag is effective only on " + "Linux."); + +GTEST_DEFINE_bool_( + throw_on_failure, + internal::BoolFromGTestEnv("throw_on_failure", false), + "When this flag is specified, a failed assertion will throw an exception " + "if exceptions are enabled or exit the program with a non-zero code " + "otherwise."); + +namespace internal { + +// Generates a random number from [0, range), using a Linear +// Congruential Generator (LCG). Crashes if 'range' is 0 or greater +// than kMaxRange. +UInt32 Random::Generate(UInt32 range) { + // These constants are the same as are used in glibc's rand(3). + state_ = (1103515245U*state_ + 12345U) % kMaxRange; + + GTEST_CHECK_(range > 0) + << "Cannot generate a number in the range [0, 0)."; + GTEST_CHECK_(range <= kMaxRange) + << "Generation of a number in [0, " << range << ") was requested, " + << "but this can only generate numbers in [0, " << kMaxRange << ")."; + + // Converting via modulus introduces a bit of downward bias, but + // it's simple, and a linear congruential generator isn't too good + // to begin with. + return state_ % range; +} + +// GTestIsInitialized() returns true iff the user has initialized +// Google Test. Useful for catching the user mistake of not initializing +// Google Test before calling RUN_ALL_TESTS(). +// +// A user must call testing::InitGoogleTest() to initialize Google +// Test. g_init_gtest_count is set to the number of times +// InitGoogleTest() has been called. We don't protect this variable +// under a mutex as it is only accessed in the main thread. +GTEST_API_ int g_init_gtest_count = 0; +static bool GTestIsInitialized() { return g_init_gtest_count != 0; } + +// Iterates over a vector of TestCases, keeping a running sum of the +// results of calling a given int-returning method on each. +// Returns the sum. +static int SumOverTestCaseList(const std::vector& case_list, + int (TestCase::*method)() const) { + int sum = 0; + for (size_t i = 0; i < case_list.size(); i++) { + sum += (case_list[i]->*method)(); + } + return sum; +} + +// Returns true iff the test case passed. +static bool TestCasePassed(const TestCase* test_case) { + return test_case->should_run() && test_case->Passed(); +} + +// Returns true iff the test case failed. +static bool TestCaseFailed(const TestCase* test_case) { + return test_case->should_run() && test_case->Failed(); +} + +// Returns true iff test_case contains at least one test that should +// run. +static bool ShouldRunTestCase(const TestCase* test_case) { + return test_case->should_run(); +} + +// AssertHelper constructor. +AssertHelper::AssertHelper(TestPartResult::Type type, + const char* file, + int line, + const char* message) + : data_(new AssertHelperData(type, file, line, message)) { +} + +AssertHelper::~AssertHelper() { + delete data_; +} + +// Message assignment, for assertion streaming support. +void AssertHelper::operator=(const Message& message) const { + UnitTest::GetInstance()-> + AddTestPartResult(data_->type, data_->file, data_->line, + AppendUserMessage(data_->message, message), + UnitTest::GetInstance()->impl() + ->CurrentOsStackTraceExceptTop(1) + // Skips the stack frame for this function itself. + ); // NOLINT +} + +// Mutex for linked pointers. +GTEST_API_ GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex); + +// Application pathname gotten in InitGoogleTest. +std::string g_executable_path; + +// Returns the current application's name, removing directory path if that +// is present. +FilePath GetCurrentExecutableName() { + FilePath result; + +#if GTEST_OS_WINDOWS + result.Set(FilePath(g_executable_path).RemoveExtension("exe")); +#else + result.Set(FilePath(g_executable_path)); +#endif // GTEST_OS_WINDOWS + + return result.RemoveDirectoryName(); +} + +// Functions for processing the gtest_output flag. + +// Returns the output format, or "" for normal printed output. +std::string UnitTestOptions::GetOutputFormat() { + const char* const gtest_output_flag = GTEST_FLAG(output).c_str(); + if (gtest_output_flag == NULL) return std::string(""); + + const char* const colon = strchr(gtest_output_flag, ':'); + return (colon == NULL) ? + std::string(gtest_output_flag) : + std::string(gtest_output_flag, colon - gtest_output_flag); +} + +// Returns the name of the requested output file, or the default if none +// was explicitly specified. +std::string UnitTestOptions::GetAbsolutePathToOutputFile() { + const char* const gtest_output_flag = GTEST_FLAG(output).c_str(); + if (gtest_output_flag == NULL) + return ""; + + const char* const colon = strchr(gtest_output_flag, ':'); + if (colon == NULL) + return internal::FilePath::ConcatPaths( + internal::FilePath( + UnitTest::GetInstance()->original_working_dir()), + internal::FilePath(kDefaultOutputFile)).string(); + + internal::FilePath output_name(colon + 1); + if (!output_name.IsAbsolutePath()) + // TODO(wan@google.com): on Windows \some\path is not an absolute + // path (as its meaning depends on the current drive), yet the + // following logic for turning it into an absolute path is wrong. + // Fix it. + output_name = internal::FilePath::ConcatPaths( + internal::FilePath(UnitTest::GetInstance()->original_working_dir()), + internal::FilePath(colon + 1)); + + if (!output_name.IsDirectory()) + return output_name.string(); + + internal::FilePath result(internal::FilePath::GenerateUniqueFileName( + output_name, internal::GetCurrentExecutableName(), + GetOutputFormat().c_str())); + return result.string(); +} + +// Returns true iff the wildcard pattern matches the string. The +// first ':' or '\0' character in pattern marks the end of it. +// +// This recursive algorithm isn't very efficient, but is clear and +// works well enough for matching test names, which are short. +bool UnitTestOptions::PatternMatchesString(const char *pattern, + const char *str) { + switch (*pattern) { + case '\0': + case ':': // Either ':' or '\0' marks the end of the pattern. + return *str == '\0'; + case '?': // Matches any single character. + return *str != '\0' && PatternMatchesString(pattern + 1, str + 1); + case '*': // Matches any string (possibly empty) of characters. + return (*str != '\0' && PatternMatchesString(pattern, str + 1)) || + PatternMatchesString(pattern + 1, str); + default: // Non-special character. Matches itself. + return *pattern == *str && + PatternMatchesString(pattern + 1, str + 1); + } +} + +bool UnitTestOptions::MatchesFilter( + const std::string& name, const char* filter) { + const char *cur_pattern = filter; + for (;;) { + if (PatternMatchesString(cur_pattern, name.c_str())) { + return true; + } + + // Finds the next pattern in the filter. + cur_pattern = strchr(cur_pattern, ':'); + + // Returns if no more pattern can be found. + if (cur_pattern == NULL) { + return false; + } + + // Skips the pattern separater (the ':' character). + cur_pattern++; + } +} + +// Returns true iff the user-specified filter matches the test case +// name and the test name. +bool UnitTestOptions::FilterMatchesTest(const std::string &test_case_name, + const std::string &test_name) { + const std::string& full_name = test_case_name + "." + test_name.c_str(); + + // Split --gtest_filter at '-', if there is one, to separate into + // positive filter and negative filter portions + const char* const p = GTEST_FLAG(filter).c_str(); + const char* const dash = strchr(p, '-'); + std::string positive; + std::string negative; + if (dash == NULL) { + positive = GTEST_FLAG(filter).c_str(); // Whole string is a positive filter + negative = ""; + } else { + positive = std::string(p, dash); // Everything up to the dash + negative = std::string(dash + 1); // Everything after the dash + if (positive.empty()) { + // Treat '-test1' as the same as '*-test1' + positive = kUniversalFilter; + } + } + + // A filter is a colon-separated list of patterns. It matches a + // test if any pattern in it matches the test. + return (MatchesFilter(full_name, positive.c_str()) && + !MatchesFilter(full_name, negative.c_str())); +} + +#if GTEST_HAS_SEH +// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the +// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise. +// This function is useful as an __except condition. +int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) { + // Google Test should handle a SEH exception if: + // 1. the user wants it to, AND + // 2. this is not a breakpoint exception, AND + // 3. this is not a C++ exception (VC++ implements them via SEH, + // apparently). + // + // SEH exception code for C++ exceptions. + // (see http://support.microsoft.com/kb/185294 for more information). + const DWORD kCxxExceptionCode = 0xe06d7363; + + bool should_handle = true; + + if (!GTEST_FLAG(catch_exceptions)) + should_handle = false; + else if (exception_code == EXCEPTION_BREAKPOINT) + should_handle = false; + else if (exception_code == kCxxExceptionCode) + should_handle = false; + + return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH; +} +#endif // GTEST_HAS_SEH + +} // namespace internal + +// The c'tor sets this object as the test part result reporter used by +// Google Test. The 'result' parameter specifies where to report the +// results. Intercepts only failures from the current thread. +ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter( + TestPartResultArray* result) + : intercept_mode_(INTERCEPT_ONLY_CURRENT_THREAD), + result_(result) { + Init(); +} + +// The c'tor sets this object as the test part result reporter used by +// Google Test. The 'result' parameter specifies where to report the +// results. +ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter( + InterceptMode intercept_mode, TestPartResultArray* result) + : intercept_mode_(intercept_mode), + result_(result) { + Init(); +} + +void ScopedFakeTestPartResultReporter::Init() { + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + if (intercept_mode_ == INTERCEPT_ALL_THREADS) { + old_reporter_ = impl->GetGlobalTestPartResultReporter(); + impl->SetGlobalTestPartResultReporter(this); + } else { + old_reporter_ = impl->GetTestPartResultReporterForCurrentThread(); + impl->SetTestPartResultReporterForCurrentThread(this); + } +} + +// The d'tor restores the test part result reporter used by Google Test +// before. +ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() { + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + if (intercept_mode_ == INTERCEPT_ALL_THREADS) { + impl->SetGlobalTestPartResultReporter(old_reporter_); + } else { + impl->SetTestPartResultReporterForCurrentThread(old_reporter_); + } +} + +// Increments the test part result count and remembers the result. +// This method is from the TestPartResultReporterInterface interface. +void ScopedFakeTestPartResultReporter::ReportTestPartResult( + const TestPartResult& result) { + result_->Append(result); +} + +namespace internal { + +// Returns the type ID of ::testing::Test. We should always call this +// instead of GetTypeId< ::testing::Test>() to get the type ID of +// testing::Test. This is to work around a suspected linker bug when +// using Google Test as a framework on Mac OS X. The bug causes +// GetTypeId< ::testing::Test>() to return different values depending +// on whether the call is from the Google Test framework itself or +// from user test code. GetTestTypeId() is guaranteed to always +// return the same value, as it always calls GetTypeId<>() from the +// gtest.cc, which is within the Google Test framework. +TypeId GetTestTypeId() { + return GetTypeId(); +} + +// The value of GetTestTypeId() as seen from within the Google Test +// library. This is solely for testing GetTestTypeId(). +extern const TypeId kTestTypeIdInGoogleTest = GetTestTypeId(); + +// This predicate-formatter checks that 'results' contains a test part +// failure of the given type and that the failure message contains the +// given substring. +AssertionResult HasOneFailure(const char* /* results_expr */, + const char* /* type_expr */, + const char* /* substr_expr */, + const TestPartResultArray& results, + TestPartResult::Type type, + const string& substr) { + const std::string expected(type == TestPartResult::kFatalFailure ? + "1 fatal failure" : + "1 non-fatal failure"); + Message msg; + if (results.size() != 1) { + msg << "Expected: " << expected << "\n" + << " Actual: " << results.size() << " failures"; + for (int i = 0; i < results.size(); i++) { + msg << "\n" << results.GetTestPartResult(i); + } + return AssertionFailure() << msg; + } + + const TestPartResult& r = results.GetTestPartResult(0); + if (r.type() != type) { + return AssertionFailure() << "Expected: " << expected << "\n" + << " Actual:\n" + << r; + } + + if (strstr(r.message(), substr.c_str()) == NULL) { + return AssertionFailure() << "Expected: " << expected << " containing \"" + << substr << "\"\n" + << " Actual:\n" + << r; + } + + return AssertionSuccess(); +} + +// The constructor of SingleFailureChecker remembers where to look up +// test part results, what type of failure we expect, and what +// substring the failure message should contain. +SingleFailureChecker:: SingleFailureChecker( + const TestPartResultArray* results, + TestPartResult::Type type, + const string& substr) + : results_(results), + type_(type), + substr_(substr) {} + +// The destructor of SingleFailureChecker verifies that the given +// TestPartResultArray contains exactly one failure that has the given +// type and contains the given substring. If that's not the case, a +// non-fatal failure will be generated. +SingleFailureChecker::~SingleFailureChecker() { + EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_); +} + +DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter( + UnitTestImpl* unit_test) : unit_test_(unit_test) {} + +void DefaultGlobalTestPartResultReporter::ReportTestPartResult( + const TestPartResult& result) { + unit_test_->current_test_result()->AddTestPartResult(result); + unit_test_->listeners()->repeater()->OnTestPartResult(result); +} + +DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter( + UnitTestImpl* unit_test) : unit_test_(unit_test) {} + +void DefaultPerThreadTestPartResultReporter::ReportTestPartResult( + const TestPartResult& result) { + unit_test_->GetGlobalTestPartResultReporter()->ReportTestPartResult(result); +} + +// Returns the global test part result reporter. +TestPartResultReporterInterface* +UnitTestImpl::GetGlobalTestPartResultReporter() { + internal::MutexLock lock(&global_test_part_result_reporter_mutex_); + return global_test_part_result_repoter_; +} + +// Sets the global test part result reporter. +void UnitTestImpl::SetGlobalTestPartResultReporter( + TestPartResultReporterInterface* reporter) { + internal::MutexLock lock(&global_test_part_result_reporter_mutex_); + global_test_part_result_repoter_ = reporter; +} + +// Returns the test part result reporter for the current thread. +TestPartResultReporterInterface* +UnitTestImpl::GetTestPartResultReporterForCurrentThread() { + return per_thread_test_part_result_reporter_.get(); +} + +// Sets the test part result reporter for the current thread. +void UnitTestImpl::SetTestPartResultReporterForCurrentThread( + TestPartResultReporterInterface* reporter) { + per_thread_test_part_result_reporter_.set(reporter); +} + +// Gets the number of successful test cases. +int UnitTestImpl::successful_test_case_count() const { + return CountIf(test_cases_, TestCasePassed); +} + +// Gets the number of failed test cases. +int UnitTestImpl::failed_test_case_count() const { + return CountIf(test_cases_, TestCaseFailed); +} + +// Gets the number of all test cases. +int UnitTestImpl::total_test_case_count() const { + return static_cast(test_cases_.size()); +} + +// Gets the number of all test cases that contain at least one test +// that should run. +int UnitTestImpl::test_case_to_run_count() const { + return CountIf(test_cases_, ShouldRunTestCase); +} + +// Gets the number of successful tests. +int UnitTestImpl::successful_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::successful_test_count); +} + +// Gets the number of failed tests. +int UnitTestImpl::failed_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::failed_test_count); +} + +// Gets the number of disabled tests that will be reported in the XML report. +int UnitTestImpl::reportable_disabled_test_count() const { + return SumOverTestCaseList(test_cases_, + &TestCase::reportable_disabled_test_count); +} + +// Gets the number of disabled tests. +int UnitTestImpl::disabled_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::disabled_test_count); +} + +// Gets the number of tests to be printed in the XML report. +int UnitTestImpl::reportable_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::reportable_test_count); +} + +// Gets the number of all tests. +int UnitTestImpl::total_test_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::total_test_count); +} + +// Gets the number of tests that should run. +int UnitTestImpl::test_to_run_count() const { + return SumOverTestCaseList(test_cases_, &TestCase::test_to_run_count); +} + +// Returns the current OS stack trace as an std::string. +// +// The maximum number of stack frames to be included is specified by +// the gtest_stack_trace_depth flag. The skip_count parameter +// specifies the number of top frames to be skipped, which doesn't +// count against the number of frames to be included. +// +// For example, if Foo() calls Bar(), which in turn calls +// CurrentOsStackTraceExceptTop(1), Foo() will be included in the +// trace but Bar() and CurrentOsStackTraceExceptTop() won't. +std::string UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) { + (void)skip_count; + return ""; +} + +// Returns the current time in milliseconds. +TimeInMillis GetTimeInMillis() { +#if GTEST_OS_WINDOWS_MOBILE || defined(__BORLANDC__) + // Difference between 1970-01-01 and 1601-01-01 in milliseconds. + // http://analogous.blogspot.com/2005/04/epoch.html + const TimeInMillis kJavaEpochToWinFileTimeDelta = + static_cast(116444736UL) * 100000UL; + const DWORD kTenthMicrosInMilliSecond = 10000; + + SYSTEMTIME now_systime; + FILETIME now_filetime; + ULARGE_INTEGER now_int64; + // TODO(kenton@google.com): Shouldn't this just use + // GetSystemTimeAsFileTime()? + GetSystemTime(&now_systime); + if (SystemTimeToFileTime(&now_systime, &now_filetime)) { + now_int64.LowPart = now_filetime.dwLowDateTime; + now_int64.HighPart = now_filetime.dwHighDateTime; + now_int64.QuadPart = (now_int64.QuadPart / kTenthMicrosInMilliSecond) - + kJavaEpochToWinFileTimeDelta; + return now_int64.QuadPart; + } + return 0; +#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_ + __timeb64 now; + +# ifdef _MSC_VER + + // MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996 + // (deprecated function) there. + // TODO(kenton@google.com): Use GetTickCount()? Or use + // SystemTimeToFileTime() +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4996) // Temporarily disables warning 4996. + _ftime64(&now); +# pragma warning(pop) // Restores the warning state. +# else + + _ftime64(&now); + +# endif // _MSC_VER + + return static_cast(now.time) * 1000 + now.millitm; +#elif GTEST_HAS_GETTIMEOFDAY_ + struct timeval now; + gettimeofday(&now, NULL); + return static_cast(now.tv_sec) * 1000 + now.tv_usec / 1000; +#else +# error "Don't know how to get the current time on your system." +#endif +} + +// Utilities + +// class String. + +#if GTEST_OS_WINDOWS_MOBILE +// Creates a UTF-16 wide string from the given ANSI string, allocating +// memory using new. The caller is responsible for deleting the return +// value using delete[]. Returns the wide string, or NULL if the +// input is NULL. +LPCWSTR String::AnsiToUtf16(const char* ansi) { + if (!ansi) return NULL; + const int length = strlen(ansi); + const int unicode_length = + MultiByteToWideChar(CP_ACP, 0, ansi, length, + NULL, 0); + WCHAR* unicode = new WCHAR[unicode_length + 1]; + MultiByteToWideChar(CP_ACP, 0, ansi, length, + unicode, unicode_length); + unicode[unicode_length] = 0; + return unicode; +} + +// Creates an ANSI string from the given wide string, allocating +// memory using new. The caller is responsible for deleting the return +// value using delete[]. Returns the ANSI string, or NULL if the +// input is NULL. +const char* String::Utf16ToAnsi(LPCWSTR utf16_str) { + if (!utf16_str) return NULL; + const int ansi_length = + WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, + NULL, 0, NULL, NULL); + char* ansi = new char[ansi_length + 1]; + WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, + ansi, ansi_length, NULL, NULL); + ansi[ansi_length] = 0; + return ansi; +} + +#endif // GTEST_OS_WINDOWS_MOBILE + +// Compares two C strings. Returns true iff they have the same content. +// +// Unlike strcmp(), this function can handle NULL argument(s). A NULL +// C string is considered different to any non-NULL C string, +// including the empty string. +bool String::CStringEquals(const char * lhs, const char * rhs) { + if ( lhs == NULL ) return rhs == NULL; + + if ( rhs == NULL ) return false; + + return strcmp(lhs, rhs) == 0; +} + +#if GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING + +// Converts an array of wide chars to a narrow string using the UTF-8 +// encoding, and streams the result to the given Message object. +static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length, + Message* msg) { + for (size_t i = 0; i != length; ) { // NOLINT + if (wstr[i] != L'\0') { + *msg << WideStringToUtf8(wstr + i, static_cast(length - i)); + while (i != length && wstr[i] != L'\0') + i++; + } else { + *msg << '\0'; + i++; + } + } +} + +#endif // GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING + +} // namespace internal + +// Constructs an empty Message. +// We allocate the stringstream separately because otherwise each use of +// ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's +// stack frame leading to huge stack frames in some cases; gcc does not reuse +// the stack space. +Message::Message() : ss_(new ::std::stringstream) { + // By default, we want there to be enough precision when printing + // a double to a Message. + *ss_ << std::setprecision(std::numeric_limits::digits10 + 2); +} + +// These two overloads allow streaming a wide C string to a Message +// using the UTF-8 encoding. +Message& Message::operator <<(const wchar_t* wide_c_str) { + return *this << internal::String::ShowWideCString(wide_c_str); +} +Message& Message::operator <<(wchar_t* wide_c_str) { + return *this << internal::String::ShowWideCString(wide_c_str); +} + +#if GTEST_HAS_STD_WSTRING +// Converts the given wide string to a narrow string using the UTF-8 +// encoding, and streams the result to this Message object. +Message& Message::operator <<(const ::std::wstring& wstr) { + internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this); + return *this; +} +#endif // GTEST_HAS_STD_WSTRING + +#if GTEST_HAS_GLOBAL_WSTRING +// Converts the given wide string to a narrow string using the UTF-8 +// encoding, and streams the result to this Message object. +Message& Message::operator <<(const ::wstring& wstr) { + internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this); + return *this; +} +#endif // GTEST_HAS_GLOBAL_WSTRING + +// Gets the text streamed to this object so far as an std::string. +// Each '\0' character in the buffer is replaced with "\\0". +std::string Message::GetString() const { + return internal::StringStreamToString(ss_.get()); +} + +// AssertionResult constructors. +// Used in EXPECT_TRUE/FALSE(assertion_result). +AssertionResult::AssertionResult(const AssertionResult& other) + : success_(other.success_), + message_(other.message_.get() != NULL ? + new ::std::string(*other.message_) : + static_cast< ::std::string*>(NULL)) { +} + +// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. +AssertionResult AssertionResult::operator!() const { + AssertionResult negation(!success_); + if (message_.get() != NULL) + negation << *message_; + return negation; +} + +// Makes a successful assertion result. +AssertionResult AssertionSuccess() { + return AssertionResult(true); +} + +// Makes a failed assertion result. +AssertionResult AssertionFailure() { + return AssertionResult(false); +} + +// Makes a failed assertion result with the given failure message. +// Deprecated; use AssertionFailure() << message. +AssertionResult AssertionFailure(const Message& message) { + return AssertionFailure() << message; +} + +namespace internal { + +// Constructs and returns the message for an equality assertion +// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure. +// +// The first four parameters are the expressions used in the assertion +// and their values, as strings. For example, for ASSERT_EQ(foo, bar) +// where foo is 5 and bar is 6, we have: +// +// expected_expression: "foo" +// actual_expression: "bar" +// expected_value: "5" +// actual_value: "6" +// +// The ignoring_case parameter is true iff the assertion is a +// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will +// be inserted into the message. +AssertionResult EqFailure(const char* expected_expression, + const char* actual_expression, + const std::string& expected_value, + const std::string& actual_value, + bool ignoring_case) { + Message msg; + msg << "Value of: " << actual_expression; + if (actual_value != actual_expression) { + msg << "\n Actual: " << actual_value; + } + + msg << "\nExpected: " << expected_expression; + if (ignoring_case) { + msg << " (ignoring case)"; + } + if (expected_value != expected_expression) { + msg << "\nWhich is: " << expected_value; + } + + return AssertionFailure() << msg; +} + +// Constructs a failure message for Boolean assertions such as EXPECT_TRUE. +std::string GetBoolAssertionFailureMessage( + const AssertionResult& assertion_result, + const char* expression_text, + const char* actual_predicate_value, + const char* expected_predicate_value) { + const char* actual_message = assertion_result.message(); + Message msg; + msg << "Value of: " << expression_text + << "\n Actual: " << actual_predicate_value; + if (actual_message[0] != '\0') + msg << " (" << actual_message << ")"; + msg << "\nExpected: " << expected_predicate_value; + return msg.GetString(); +} + +// Helper function for implementing ASSERT_NEAR. +AssertionResult DoubleNearPredFormat(const char* expr1, + const char* expr2, + const char* abs_error_expr, + double val1, + double val2, + double abs_error) { + const double diff = fabs(val1 - val2); + if (diff <= abs_error) return AssertionSuccess(); + + // TODO(wan): do not print the value of an expression if it's + // already a literal. + return AssertionFailure() + << "The difference between " << expr1 << " and " << expr2 + << " is " << diff << ", which exceeds " << abs_error_expr << ", where\n" + << expr1 << " evaluates to " << val1 << ",\n" + << expr2 << " evaluates to " << val2 << ", and\n" + << abs_error_expr << " evaluates to " << abs_error << "."; +} + + +// Helper template for implementing FloatLE() and DoubleLE(). +template +AssertionResult FloatingPointLE(const char* expr1, + const char* expr2, + RawType val1, + RawType val2) { + // Returns success if val1 is less than val2, + if (val1 < val2) { + return AssertionSuccess(); + } + + // or if val1 is almost equal to val2. + const FloatingPoint lhs(val1), rhs(val2); + if (lhs.AlmostEquals(rhs)) { + return AssertionSuccess(); + } + + // Note that the above two checks will both fail if either val1 or + // val2 is NaN, as the IEEE floating-point standard requires that + // any predicate involving a NaN must return false. + + ::std::stringstream val1_ss; + val1_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << val1; + + ::std::stringstream val2_ss; + val2_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << val2; + + return AssertionFailure() + << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n" + << " Actual: " << StringStreamToString(&val1_ss) << " vs " + << StringStreamToString(&val2_ss); +} + +} // namespace internal + +// Asserts that val1 is less than, or almost equal to, val2. Fails +// otherwise. In particular, it fails if either val1 or val2 is NaN. +AssertionResult FloatLE(const char* expr1, const char* expr2, + float val1, float val2) { + return internal::FloatingPointLE(expr1, expr2, val1, val2); +} + +// Asserts that val1 is less than, or almost equal to, val2. Fails +// otherwise. In particular, it fails if either val1 or val2 is NaN. +AssertionResult DoubleLE(const char* expr1, const char* expr2, + double val1, double val2) { + return internal::FloatingPointLE(expr1, expr2, val1, val2); +} + +namespace internal { + +// The helper function for {ASSERT|EXPECT}_EQ with int or enum +// arguments. +AssertionResult CmpHelperEQ(const char* expected_expression, + const char* actual_expression, + BiggestInt expected, + BiggestInt actual) { + if (expected == actual) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + FormatForComparisonFailureMessage(expected, actual), + FormatForComparisonFailureMessage(actual, expected), + false); +} + +// A macro for implementing the helper functions needed to implement +// ASSERT_?? and EXPECT_?? with integer or enum arguments. It is here +// just to avoid copy-and-paste of similar code. +#define GTEST_IMPL_CMP_HELPER_(op_name, op)\ +AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ + BiggestInt val1, BiggestInt val2) {\ + if (val1 op val2) {\ + return AssertionSuccess();\ + } else {\ + return AssertionFailure() \ + << "Expected: (" << expr1 << ") " #op " (" << expr2\ + << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\ + << " vs " << FormatForComparisonFailureMessage(val2, val1);\ + }\ +} + +// Implements the helper function for {ASSERT|EXPECT}_NE with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(NE, !=) +// Implements the helper function for {ASSERT|EXPECT}_LE with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(LE, <=) +// Implements the helper function for {ASSERT|EXPECT}_LT with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(LT, < ) +// Implements the helper function for {ASSERT|EXPECT}_GE with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(GE, >=) +// Implements the helper function for {ASSERT|EXPECT}_GT with int or +// enum arguments. +GTEST_IMPL_CMP_HELPER_(GT, > ) + +#undef GTEST_IMPL_CMP_HELPER_ + +// The helper function for {ASSERT|EXPECT}_STREQ. +AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual) { + if (String::CStringEquals(expected, actual)) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + PrintToString(expected), + PrintToString(actual), + false); +} + +// The helper function for {ASSERT|EXPECT}_STRCASEEQ. +AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual) { + if (String::CaseInsensitiveCStringEquals(expected, actual)) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + PrintToString(expected), + PrintToString(actual), + true); +} + +// The helper function for {ASSERT|EXPECT}_STRNE. +AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2) { + if (!String::CStringEquals(s1, s2)) { + return AssertionSuccess(); + } else { + return AssertionFailure() << "Expected: (" << s1_expression << ") != (" + << s2_expression << "), actual: \"" + << s1 << "\" vs \"" << s2 << "\""; + } +} + +// The helper function for {ASSERT|EXPECT}_STRCASENE. +AssertionResult CmpHelperSTRCASENE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2) { + if (!String::CaseInsensitiveCStringEquals(s1, s2)) { + return AssertionSuccess(); + } else { + return AssertionFailure() + << "Expected: (" << s1_expression << ") != (" + << s2_expression << ") (ignoring case), actual: \"" + << s1 << "\" vs \"" << s2 << "\""; + } +} + +} // namespace internal + +namespace { + +// Helper functions for implementing IsSubString() and IsNotSubstring(). + +// This group of overloaded functions return true iff needle is a +// substring of haystack. NULL is considered a substring of itself +// only. + +bool IsSubstringPred(const char* needle, const char* haystack) { + if (needle == NULL || haystack == NULL) + return needle == haystack; + + return strstr(haystack, needle) != NULL; +} + +bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) { + if (needle == NULL || haystack == NULL) + return needle == haystack; + + return wcsstr(haystack, needle) != NULL; +} + +// StringType here can be either ::std::string or ::std::wstring. +template +bool IsSubstringPred(const StringType& needle, + const StringType& haystack) { + return haystack.find(needle) != StringType::npos; +} + +// This function implements either IsSubstring() or IsNotSubstring(), +// depending on the value of the expected_to_be_substring parameter. +// StringType here can be const char*, const wchar_t*, ::std::string, +// or ::std::wstring. +template +AssertionResult IsSubstringImpl( + bool expected_to_be_substring, + const char* needle_expr, const char* haystack_expr, + const StringType& needle, const StringType& haystack) { + if (IsSubstringPred(needle, haystack) == expected_to_be_substring) + return AssertionSuccess(); + + const bool is_wide_string = sizeof(needle[0]) > 1; + const char* const begin_string_quote = is_wide_string ? "L\"" : "\""; + return AssertionFailure() + << "Value of: " << needle_expr << "\n" + << " Actual: " << begin_string_quote << needle << "\"\n" + << "Expected: " << (expected_to_be_substring ? "" : "not ") + << "a substring of " << haystack_expr << "\n" + << "Which is: " << begin_string_quote << haystack << "\""; +} + +} // namespace + +// IsSubstring() and IsNotSubstring() check whether needle is a +// substring of haystack (NULL is considered a substring of itself +// only), and return an appropriate error message when they fail. + +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} + +#if GTEST_HAS_STD_WSTRING +AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack) { + return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); +} + +AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack) { + return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); +} +#endif // GTEST_HAS_STD_WSTRING + +namespace internal { + +#if GTEST_OS_WINDOWS + +namespace { + +// Helper function for IsHRESULT{SuccessFailure} predicates +AssertionResult HRESULTFailureHelper(const char* expr, + const char* expected, + long hr) { // NOLINT +# if GTEST_OS_WINDOWS_MOBILE + + // Windows CE doesn't support FormatMessage. + const char error_text[] = ""; + +# else + + // Looks up the human-readable system message for the HRESULT code + // and since we're not passing any params to FormatMessage, we don't + // want inserts expanded. + const DWORD kFlags = FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS; + const DWORD kBufSize = 4096; + // Gets the system's human readable message string for this HRESULT. + char error_text[kBufSize] = { '\0' }; + DWORD message_length = ::FormatMessageA(kFlags, + 0, // no source, we're asking system + hr, // the error + 0, // no line width restrictions + error_text, // output buffer + kBufSize, // buf size + NULL); // no arguments for inserts + // Trims tailing white space (FormatMessage leaves a trailing CR-LF) + for (; message_length && IsSpace(error_text[message_length - 1]); + --message_length) { + error_text[message_length - 1] = '\0'; + } + +# endif // GTEST_OS_WINDOWS_MOBILE + + const std::string error_hex("0x" + String::FormatHexInt(hr)); + return ::testing::AssertionFailure() + << "Expected: " << expr << " " << expected << ".\n" + << " Actual: " << error_hex << " " << error_text << "\n"; +} + +} // namespace + +AssertionResult IsHRESULTSuccess(const char* expr, long hr) { // NOLINT + if (SUCCEEDED(hr)) { + return AssertionSuccess(); + } + return HRESULTFailureHelper(expr, "succeeds", hr); +} + +AssertionResult IsHRESULTFailure(const char* expr, long hr) { // NOLINT + if (FAILED(hr)) { + return AssertionSuccess(); + } + return HRESULTFailureHelper(expr, "fails", hr); +} + +#endif // GTEST_OS_WINDOWS + +// Utility functions for encoding Unicode text (wide strings) in +// UTF-8. + +// A Unicode code-point can have upto 21 bits, and is encoded in UTF-8 +// like this: +// +// Code-point length Encoding +// 0 - 7 bits 0xxxxxxx +// 8 - 11 bits 110xxxxx 10xxxxxx +// 12 - 16 bits 1110xxxx 10xxxxxx 10xxxxxx +// 17 - 21 bits 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + +// The maximum code-point a one-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint1 = (static_cast(1) << 7) - 1; + +// The maximum code-point a two-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint2 = (static_cast(1) << (5 + 6)) - 1; + +// The maximum code-point a three-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint3 = (static_cast(1) << (4 + 2*6)) - 1; + +// The maximum code-point a four-byte UTF-8 sequence can represent. +const UInt32 kMaxCodePoint4 = (static_cast(1) << (3 + 3*6)) - 1; + +// Chops off the n lowest bits from a bit pattern. Returns the n +// lowest bits. As a side effect, the original bit pattern will be +// shifted to the right by n bits. +inline UInt32 ChopLowBits(UInt32* bits, int n) { + const UInt32 low_bits = *bits & ((static_cast(1) << n) - 1); + *bits >>= n; + return low_bits; +} + +// Converts a Unicode code point to a narrow string in UTF-8 encoding. +// code_point parameter is of type UInt32 because wchar_t may not be +// wide enough to contain a code point. +// If the code_point is not a valid Unicode code point +// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted +// to "(Invalid Unicode 0xXXXXXXXX)". +std::string CodePointToUtf8(UInt32 code_point) { + if (code_point > kMaxCodePoint4) { + return "(Invalid Unicode 0x" + String::FormatHexInt(code_point) + ")"; + } + + char str[5]; // Big enough for the largest valid code point. + if (code_point <= kMaxCodePoint1) { + str[1] = '\0'; + str[0] = static_cast(code_point); // 0xxxxxxx + } else if (code_point <= kMaxCodePoint2) { + str[2] = '\0'; + str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[0] = static_cast(0xC0 | code_point); // 110xxxxx + } else if (code_point <= kMaxCodePoint3) { + str[3] = '\0'; + str[2] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[0] = static_cast(0xE0 | code_point); // 1110xxxx + } else { // code_point <= kMaxCodePoint4 + str[4] = '\0'; + str[3] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[2] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx + str[0] = static_cast(0xF0 | code_point); // 11110xxx + } + return str; +} + +// The following two functions only make sense if the the system +// uses UTF-16 for wide string encoding. All supported systems +// with 16 bit wchar_t (Windows, Cygwin, Symbian OS) do use UTF-16. + +// Determines if the arguments constitute UTF-16 surrogate pair +// and thus should be combined into a single Unicode code point +// using CreateCodePointFromUtf16SurrogatePair. +inline bool IsUtf16SurrogatePair(wchar_t first, wchar_t second) { + return sizeof(wchar_t) == 2 && + (first & 0xFC00) == 0xD800 && (second & 0xFC00) == 0xDC00; +} + +// Creates a Unicode code point from UTF16 surrogate pair. +inline UInt32 CreateCodePointFromUtf16SurrogatePair(wchar_t first, + wchar_t second) { + const UInt32 mask = (1 << 10) - 1; + return (sizeof(wchar_t) == 2) ? + (((first & mask) << 10) | (second & mask)) + 0x10000 : + // This function should not be called when the condition is + // false, but we provide a sensible default in case it is. + static_cast(first); +} + +// Converts a wide string to a narrow string in UTF-8 encoding. +// The wide string is assumed to have the following encoding: +// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS) +// UTF-32 if sizeof(wchar_t) == 4 (on Linux) +// Parameter str points to a null-terminated wide string. +// Parameter num_chars may additionally limit the number +// of wchar_t characters processed. -1 is used when the entire string +// should be processed. +// If the string contains code points that are not valid Unicode code points +// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output +// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding +// and contains invalid UTF-16 surrogate pairs, values in those pairs +// will be encoded as individual Unicode characters from Basic Normal Plane. +std::string WideStringToUtf8(const wchar_t* str, int num_chars) { + if (num_chars == -1) + num_chars = static_cast(wcslen(str)); + + ::std::stringstream stream; + for (int i = 0; i < num_chars; ++i) { + UInt32 unicode_code_point; + + if (str[i] == L'\0') { + break; + } else if (i + 1 < num_chars && IsUtf16SurrogatePair(str[i], str[i + 1])) { + unicode_code_point = CreateCodePointFromUtf16SurrogatePair(str[i], + str[i + 1]); + i++; + } else { + unicode_code_point = static_cast(str[i]); + } + + stream << CodePointToUtf8(unicode_code_point); + } + return StringStreamToString(&stream); +} + +// Converts a wide C string to an std::string using the UTF-8 encoding. +// NULL will be converted to "(null)". +std::string String::ShowWideCString(const wchar_t * wide_c_str) { + if (wide_c_str == NULL) return "(null)"; + + return internal::WideStringToUtf8(wide_c_str, -1); +} + +// Compares two wide C strings. Returns true iff they have the same +// content. +// +// Unlike wcscmp(), this function can handle NULL argument(s). A NULL +// C string is considered different to any non-NULL C string, +// including the empty string. +bool String::WideCStringEquals(const wchar_t * lhs, const wchar_t * rhs) { + if (lhs == NULL) return rhs == NULL; + + if (rhs == NULL) return false; + + return wcscmp(lhs, rhs) == 0; +} + +// Helper function for *_STREQ on wide strings. +AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const wchar_t* expected, + const wchar_t* actual) { + if (String::WideCStringEquals(expected, actual)) { + return AssertionSuccess(); + } + + return EqFailure(expected_expression, + actual_expression, + PrintToString(expected), + PrintToString(actual), + false); +} + +// Helper function for *_STRNE on wide strings. +AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const wchar_t* s1, + const wchar_t* s2) { + if (!String::WideCStringEquals(s1, s2)) { + return AssertionSuccess(); + } + + return AssertionFailure() << "Expected: (" << s1_expression << ") != (" + << s2_expression << "), actual: " + << PrintToString(s1) + << " vs " << PrintToString(s2); +} + +// Compares two C strings, ignoring case. Returns true iff they have +// the same content. +// +// Unlike strcasecmp(), this function can handle NULL argument(s). A +// NULL C string is considered different to any non-NULL C string, +// including the empty string. +bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) { + if (lhs == NULL) + return rhs == NULL; + if (rhs == NULL) + return false; + return posix::StrCaseCmp(lhs, rhs) == 0; +} + + // Compares two wide C strings, ignoring case. Returns true iff they + // have the same content. + // + // Unlike wcscasecmp(), this function can handle NULL argument(s). + // A NULL C string is considered different to any non-NULL wide C string, + // including the empty string. + // NB: The implementations on different platforms slightly differ. + // On windows, this method uses _wcsicmp which compares according to LC_CTYPE + // environment variable. On GNU platform this method uses wcscasecmp + // which compares according to LC_CTYPE category of the current locale. + // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the + // current locale. +bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs, + const wchar_t* rhs) { + if (lhs == NULL) return rhs == NULL; + + if (rhs == NULL) return false; + +#if GTEST_OS_WINDOWS + return _wcsicmp(lhs, rhs) == 0; +#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID + return wcscasecmp(lhs, rhs) == 0; +#else + // Android, Mac OS X and Cygwin don't define wcscasecmp. + // Other unknown OSes may not define it either. + wint_t left, right; + do { + left = towlower(*lhs++); + right = towlower(*rhs++); + } while (left && left == right); + return left == right; +#endif // OS selector +} + +// Returns true iff str ends with the given suffix, ignoring case. +// Any string is considered to end with an empty suffix. +bool String::EndsWithCaseInsensitive( + const std::string& str, const std::string& suffix) { + const size_t str_len = str.length(); + const size_t suffix_len = suffix.length(); + return (str_len >= suffix_len) && + CaseInsensitiveCStringEquals(str.c_str() + str_len - suffix_len, + suffix.c_str()); +} + +// Formats an int value as "%02d". +std::string String::FormatIntWidth2(int value) { + std::stringstream ss; + ss << std::setfill('0') << std::setw(2) << value; + return ss.str(); +} + +// Formats an int value as "%X". +std::string String::FormatHexInt(int value) { + std::stringstream ss; + ss << std::hex << std::uppercase << value; + return ss.str(); +} + +// Formats a byte as "%02X". +std::string String::FormatByte(unsigned char value) { + std::stringstream ss; + ss << std::setfill('0') << std::setw(2) << std::hex << std::uppercase + << static_cast(value); + return ss.str(); +} + +// Converts the buffer in a stringstream to an std::string, converting NUL +// bytes to "\\0" along the way. +std::string StringStreamToString(::std::stringstream* ss) { + const ::std::string& str = ss->str(); + const char* const start = str.c_str(); + const char* const end = start + str.length(); + + std::string result; + result.reserve(2 * (end - start)); + for (const char* ch = start; ch != end; ++ch) { + if (*ch == '\0') { + result += "\\0"; // Replaces NUL with "\\0"; + } else { + result += *ch; + } + } + + return result; +} + +// Appends the user-supplied message to the Google-Test-generated message. +std::string AppendUserMessage(const std::string& gtest_msg, + const Message& user_msg) { + // Appends the user message if it's non-empty. + const std::string user_msg_string = user_msg.GetString(); + if (user_msg_string.empty()) { + return gtest_msg; + } + + return gtest_msg + "\n" + user_msg_string; +} + +} // namespace internal + +// class TestResult + +// Creates an empty TestResult. +TestResult::TestResult() + : death_test_count_(0), + elapsed_time_(0) { +} + +// D'tor. +TestResult::~TestResult() { +} + +// Returns the i-th test part result among all the results. i can +// range from 0 to total_part_count() - 1. If i is not in that range, +// aborts the program. +const TestPartResult& TestResult::GetTestPartResult(int i) const { + if (i < 0 || i >= total_part_count()) + internal::posix::Abort(); + return test_part_results_.at(i); +} + +// Returns the i-th test property. i can range from 0 to +// test_property_count() - 1. If i is not in that range, aborts the +// program. +const TestProperty& TestResult::GetTestProperty(int i) const { + if (i < 0 || i >= test_property_count()) + internal::posix::Abort(); + return test_properties_.at(i); +} + +// Clears the test part results. +void TestResult::ClearTestPartResults() { + test_part_results_.clear(); +} + +// Adds a test part result to the list. +void TestResult::AddTestPartResult(const TestPartResult& test_part_result) { + test_part_results_.push_back(test_part_result); +} + +// Adds a test property to the list. If a property with the same key as the +// supplied property is already represented, the value of this test_property +// replaces the old value for that key. +void TestResult::RecordProperty(const std::string& xml_element, + const TestProperty& test_property) { + if (!ValidateTestProperty(xml_element, test_property)) { + return; + } + internal::MutexLock lock(&test_properites_mutex_); + const std::vector::iterator property_with_matching_key = + std::find_if(test_properties_.begin(), test_properties_.end(), + internal::TestPropertyKeyIs(test_property.key())); + if (property_with_matching_key == test_properties_.end()) { + test_properties_.push_back(test_property); + return; + } + property_with_matching_key->SetValue(test_property.value()); +} + +// The list of reserved attributes used in the element of XML +// output. +static const char* const kReservedTestSuitesAttributes[] = { + "disabled", + "errors", + "failures", + "name", + "random_seed", + "tests", + "time", + "timestamp" +}; + +// The list of reserved attributes used in the element of XML +// output. +static const char* const kReservedTestSuiteAttributes[] = { + "disabled", + "errors", + "failures", + "name", + "tests", + "time" +}; + +// The list of reserved attributes used in the element of XML output. +static const char* const kReservedTestCaseAttributes[] = { + "classname", + "name", + "status", + "time", + "type_param", + "value_param" +}; + +template +std::vector ArrayAsVector(const char* const (&array)[kSize]) { + return std::vector(array, array + kSize); +} + +static std::vector GetReservedAttributesForElement( + const std::string& xml_element) { + if (xml_element == "testsuites") { + return ArrayAsVector(kReservedTestSuitesAttributes); + } else if (xml_element == "testsuite") { + return ArrayAsVector(kReservedTestSuiteAttributes); + } else if (xml_element == "testcase") { + return ArrayAsVector(kReservedTestCaseAttributes); + } else { + GTEST_CHECK_(false) << "Unrecognized xml_element provided: " << xml_element; + } + // This code is unreachable but some compilers may not realizes that. + return std::vector(); +} + +static std::string FormatWordList(const std::vector& words) { + Message word_list; + for (size_t i = 0; i < words.size(); ++i) { + if (i > 0 && words.size() > 2) { + word_list << ", "; + } + if (i == words.size() - 1) { + word_list << "and "; + } + word_list << "'" << words[i] << "'"; + } + return word_list.GetString(); +} + +bool ValidateTestPropertyName(const std::string& property_name, + const std::vector& reserved_names) { + if (std::find(reserved_names.begin(), reserved_names.end(), property_name) != + reserved_names.end()) { + ADD_FAILURE() << "Reserved key used in RecordProperty(): " << property_name + << " (" << FormatWordList(reserved_names) + << " are reserved by " << GTEST_NAME_ << ")"; + return false; + } + return true; +} + +// Adds a failure if the key is a reserved attribute of the element named +// xml_element. Returns true if the property is valid. +bool TestResult::ValidateTestProperty(const std::string& xml_element, + const TestProperty& test_property) { + return ValidateTestPropertyName(test_property.key(), + GetReservedAttributesForElement(xml_element)); +} + +// Clears the object. +void TestResult::Clear() { + test_part_results_.clear(); + test_properties_.clear(); + death_test_count_ = 0; + elapsed_time_ = 0; +} + +// Returns true iff the test failed. +bool TestResult::Failed() const { + for (int i = 0; i < total_part_count(); ++i) { + if (GetTestPartResult(i).failed()) + return true; + } + return false; +} + +// Returns true iff the test part fatally failed. +static bool TestPartFatallyFailed(const TestPartResult& result) { + return result.fatally_failed(); +} + +// Returns true iff the test fatally failed. +bool TestResult::HasFatalFailure() const { + return CountIf(test_part_results_, TestPartFatallyFailed) > 0; +} + +// Returns true iff the test part non-fatally failed. +static bool TestPartNonfatallyFailed(const TestPartResult& result) { + return result.nonfatally_failed(); +} + +// Returns true iff the test has a non-fatal failure. +bool TestResult::HasNonfatalFailure() const { + return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0; +} + +// Gets the number of all test parts. This is the sum of the number +// of successful test parts and the number of failed test parts. +int TestResult::total_part_count() const { + return static_cast(test_part_results_.size()); +} + +// Returns the number of the test properties. +int TestResult::test_property_count() const { + return static_cast(test_properties_.size()); +} + +// class Test + +// Creates a Test object. + +// The c'tor saves the values of all Google Test flags. +Test::Test() + : gtest_flag_saver_(new internal::GTestFlagSaver) { +} + +// The d'tor restores the values of all Google Test flags. +Test::~Test() { + delete gtest_flag_saver_; +} + +// Sets up the test fixture. +// +// A sub-class may override this. +void Test::SetUp() { +} + +// Tears down the test fixture. +// +// A sub-class may override this. +void Test::TearDown() { +} + +// Allows user supplied key value pairs to be recorded for later output. +void Test::RecordProperty(const std::string& key, const std::string& value) { + UnitTest::GetInstance()->RecordProperty(key, value); +} + +// Allows user supplied key value pairs to be recorded for later output. +void Test::RecordProperty(const std::string& key, int value) { + Message value_message; + value_message << value; + RecordProperty(key, value_message.GetString().c_str()); +} + +namespace internal { + +void ReportFailureInUnknownLocation(TestPartResult::Type result_type, + const std::string& message) { + // This function is a friend of UnitTest and as such has access to + // AddTestPartResult. + UnitTest::GetInstance()->AddTestPartResult( + result_type, + NULL, // No info about the source file where the exception occurred. + -1, // We have no info on which line caused the exception. + message, + ""); // No stack trace, either. +} + +} // namespace internal + +// Google Test requires all tests in the same test case to use the same test +// fixture class. This function checks if the current test has the +// same fixture class as the first test in the current test case. If +// yes, it returns true; otherwise it generates a Google Test failure and +// returns false. +bool Test::HasSameFixtureClass() { + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + const TestCase* const test_case = impl->current_test_case(); + + // Info about the first test in the current test case. + const TestInfo* const first_test_info = test_case->test_info_list()[0]; + const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_; + const char* const first_test_name = first_test_info->name(); + + // Info about the current test. + const TestInfo* const this_test_info = impl->current_test_info(); + const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_; + const char* const this_test_name = this_test_info->name(); + + if (this_fixture_id != first_fixture_id) { + // Is the first test defined using TEST? + const bool first_is_TEST = first_fixture_id == internal::GetTestTypeId(); + // Is this test defined using TEST? + const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId(); + + if (first_is_TEST || this_is_TEST) { + // The user mixed TEST and TEST_F in this test case - we'll tell + // him/her how to fix it. + + // Gets the name of the TEST and the name of the TEST_F. Note + // that first_is_TEST and this_is_TEST cannot both be true, as + // the fixture IDs are different for the two tests. + const char* const TEST_name = + first_is_TEST ? first_test_name : this_test_name; + const char* const TEST_F_name = + first_is_TEST ? this_test_name : first_test_name; + + ADD_FAILURE() + << "All tests in the same test case must use the same test fixture\n" + << "class, so mixing TEST_F and TEST in the same test case is\n" + << "illegal. In test case " << this_test_info->test_case_name() + << ",\n" + << "test " << TEST_F_name << " is defined using TEST_F but\n" + << "test " << TEST_name << " is defined using TEST. You probably\n" + << "want to change the TEST to TEST_F or move it to another test\n" + << "case."; + } else { + // The user defined two fixture classes with the same name in + // two namespaces - we'll tell him/her how to fix it. + ADD_FAILURE() + << "All tests in the same test case must use the same test fixture\n" + << "class. However, in test case " + << this_test_info->test_case_name() << ",\n" + << "you defined test " << first_test_name + << " and test " << this_test_name << "\n" + << "using two different test fixture classes. This can happen if\n" + << "the two classes are from different namespaces or translation\n" + << "units and have the same name. You should probably rename one\n" + << "of the classes to put the tests into different test cases."; + } + return false; + } + + return true; +} + +#if GTEST_HAS_SEH + +// Adds an "exception thrown" fatal failure to the current test. This +// function returns its result via an output parameter pointer because VC++ +// prohibits creation of objects with destructors on stack in functions +// using __try (see error C2712). +static std::string* FormatSehExceptionMessage(DWORD exception_code, + const char* location) { + Message message; + message << "SEH exception with code 0x" << std::setbase(16) << + exception_code << std::setbase(10) << " thrown in " << location << "."; + + return new std::string(message.GetString()); +} + +#endif // GTEST_HAS_SEH + +namespace internal { + +#if GTEST_HAS_EXCEPTIONS + +// Adds an "exception thrown" fatal failure to the current test. +static std::string FormatCxxExceptionMessage(const char* description, + const char* location) { + Message message; + if (description != NULL) { + message << "C++ exception with description \"" << description << "\""; + } else { + message << "Unknown C++ exception"; + } + message << " thrown in " << location << "."; + + return message.GetString(); +} + +static std::string PrintTestPartResultToString( + const TestPartResult& test_part_result); + +GoogleTestFailureException::GoogleTestFailureException( + const TestPartResult& failure) + : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {} + +#endif // GTEST_HAS_EXCEPTIONS + +// We put these helper functions in the internal namespace as IBM's xlC +// compiler rejects the code if they were declared static. + +// Runs the given method and handles SEH exceptions it throws, when +// SEH is supported; returns the 0-value for type Result in case of an +// SEH exception. (Microsoft compilers cannot handle SEH and C++ +// exceptions in the same function. Therefore, we provide a separate +// wrapper function for handling SEH exceptions.) +template +Result HandleSehExceptionsInMethodIfSupported( + T* object, Result (T::*method)(), const char* location) { +#if GTEST_HAS_SEH + __try { + return (object->*method)(); + } __except (internal::UnitTestOptions::GTestShouldProcessSEH( // NOLINT + GetExceptionCode())) { + // We create the exception message on the heap because VC++ prohibits + // creation of objects with destructors on stack in functions using __try + // (see error C2712). + std::string* exception_message = FormatSehExceptionMessage( + GetExceptionCode(), location); + internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure, + *exception_message); + delete exception_message; + return static_cast(0); + } +#else + (void)location; + return (object->*method)(); +#endif // GTEST_HAS_SEH +} + +// Runs the given method and catches and reports C++ and/or SEH-style +// exceptions, if they are supported; returns the 0-value for type +// Result in case of an SEH exception. +template +Result HandleExceptionsInMethodIfSupported( + T* object, Result (T::*method)(), const char* location) { + // NOTE: The user code can affect the way in which Google Test handles + // exceptions by setting GTEST_FLAG(catch_exceptions), but only before + // RUN_ALL_TESTS() starts. It is technically possible to check the flag + // after the exception is caught and either report or re-throw the + // exception based on the flag's value: + // + // try { + // // Perform the test method. + // } catch (...) { + // if (GTEST_FLAG(catch_exceptions)) + // // Report the exception as failure. + // else + // throw; // Re-throws the original exception. + // } + // + // However, the purpose of this flag is to allow the program to drop into + // the debugger when the exception is thrown. On most platforms, once the + // control enters the catch block, the exception origin information is + // lost and the debugger will stop the program at the point of the + // re-throw in this function -- instead of at the point of the original + // throw statement in the code under test. For this reason, we perform + // the check early, sacrificing the ability to affect Google Test's + // exception handling in the method where the exception is thrown. + if (internal::GetUnitTestImpl()->catch_exceptions()) { +#if GTEST_HAS_EXCEPTIONS + try { + return HandleSehExceptionsInMethodIfSupported(object, method, location); + } catch (const internal::GoogleTestFailureException&) { // NOLINT + // This exception type can only be thrown by a failed Google + // Test assertion with the intention of letting another testing + // framework catch it. Therefore we just re-throw it. + throw; + } catch (const std::exception& e) { // NOLINT + internal::ReportFailureInUnknownLocation( + TestPartResult::kFatalFailure, + FormatCxxExceptionMessage(e.what(), location)); + } catch (...) { // NOLINT + internal::ReportFailureInUnknownLocation( + TestPartResult::kFatalFailure, + FormatCxxExceptionMessage(NULL, location)); + } + return static_cast(0); +#else + return HandleSehExceptionsInMethodIfSupported(object, method, location); +#endif // GTEST_HAS_EXCEPTIONS + } else { + return (object->*method)(); + } +} + +} // namespace internal + +// Runs the test and updates the test result. +void Test::Run() { + if (!HasSameFixtureClass()) return; + + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()"); + // We will run the test only if SetUp() was successful. + if (!HasFatalFailure()) { + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &Test::TestBody, "the test body"); + } + + // However, we want to clean up as much as possible. Hence we will + // always call TearDown(), even if SetUp() or the test body has + // failed. + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &Test::TearDown, "TearDown()"); +} + +// Returns true iff the current test has a fatal failure. +bool Test::HasFatalFailure() { + return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure(); +} + +// Returns true iff the current test has a non-fatal failure. +bool Test::HasNonfatalFailure() { + return internal::GetUnitTestImpl()->current_test_result()-> + HasNonfatalFailure(); +} + +// class TestInfo + +// Constructs a TestInfo object. It assumes ownership of the test factory +// object. +TestInfo::TestInfo(const std::string& a_test_case_name, + const std::string& a_name, + const char* a_type_param, + const char* a_value_param, + internal::TypeId fixture_class_id, + internal::TestFactoryBase* factory) + : test_case_name_(a_test_case_name), + name_(a_name), + type_param_(a_type_param ? new std::string(a_type_param) : NULL), + value_param_(a_value_param ? new std::string(a_value_param) : NULL), + fixture_class_id_(fixture_class_id), + should_run_(false), + is_disabled_(false), + matches_filter_(false), + factory_(factory), + result_() {} + +// Destructs a TestInfo object. +TestInfo::~TestInfo() { delete factory_; } + +namespace internal { + +// Creates a new TestInfo object and registers it with Google Test; +// returns the created object. +// +// Arguments: +// +// test_case_name: name of the test case +// name: name of the test +// type_param: the name of the test's type parameter, or NULL if +// this is not a typed or a type-parameterized test. +// value_param: text representation of the test's value parameter, +// or NULL if this is not a value-parameterized test. +// fixture_class_id: ID of the test fixture class +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +// factory: pointer to the factory that creates a test object. +// The newly created TestInfo instance will assume +// ownership of the factory object. +TestInfo* MakeAndRegisterTestInfo( + const char* test_case_name, + const char* name, + const char* type_param, + const char* value_param, + TypeId fixture_class_id, + SetUpTestCaseFunc set_up_tc, + TearDownTestCaseFunc tear_down_tc, + TestFactoryBase* factory) { + TestInfo* const test_info = + new TestInfo(test_case_name, name, type_param, value_param, + fixture_class_id, factory); + GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info); + return test_info; +} + +#if GTEST_HAS_PARAM_TEST +void ReportInvalidTestCaseType(const char* test_case_name, + const char* file, int line) { + Message errors; + errors + << "Attempted redefinition of test case " << test_case_name << ".\n" + << "All tests in the same test case must use the same test fixture\n" + << "class. However, in test case " << test_case_name << ", you tried\n" + << "to define a test using a fixture class different from the one\n" + << "used earlier. This can happen if the two fixture classes are\n" + << "from different namespaces and have the same name. You should\n" + << "probably rename one of the classes to put the tests into different\n" + << "test cases."; + + fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), + errors.GetString().c_str()); +} +#endif // GTEST_HAS_PARAM_TEST + +} // namespace internal + +namespace { + +// A predicate that checks the test name of a TestInfo against a known +// value. +// +// This is used for implementation of the TestCase class only. We put +// it in the anonymous namespace to prevent polluting the outer +// namespace. +// +// TestNameIs is copyable. +class TestNameIs { + public: + // Constructor. + // + // TestNameIs has NO default constructor. + explicit TestNameIs(const char* name) + : name_(name) {} + + // Returns true iff the test name of test_info matches name_. + bool operator()(const TestInfo * test_info) const { + return test_info && test_info->name() == name_; + } + + private: + std::string name_; +}; + +} // namespace + +namespace internal { + +// This method expands all parameterized tests registered with macros TEST_P +// and INSTANTIATE_TEST_CASE_P into regular tests and registers those. +// This will be done just once during the program runtime. +void UnitTestImpl::RegisterParameterizedTests() { +#if GTEST_HAS_PARAM_TEST + if (!parameterized_tests_registered_) { + parameterized_test_registry_.RegisterTests(); + parameterized_tests_registered_ = true; + } +#endif +} + +} // namespace internal + +// Creates the test object, runs it, records its result, and then +// deletes it. +void TestInfo::Run() { + if (!should_run_) return; + + // Tells UnitTest where to store test result. + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + impl->set_current_test_info(this); + + TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); + + // Notifies the unit test event listeners that a test is about to start. + repeater->OnTestStart(*this); + + const TimeInMillis start = internal::GetTimeInMillis(); + + impl->os_stack_trace_getter()->UponLeavingGTest(); + + // Creates the test object. + Test* const test = internal::HandleExceptionsInMethodIfSupported( + factory_, &internal::TestFactoryBase::CreateTest, + "the test fixture's constructor"); + + // Runs the test only if the test object was created and its + // constructor didn't generate a fatal failure. + if ((test != NULL) && !Test::HasFatalFailure()) { + // This doesn't throw as all user code that can throw are wrapped into + // exception handling code. + test->Run(); + } + + // Deletes the test object. + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + test, &Test::DeleteSelf_, "the test fixture's destructor"); + + result_.set_elapsed_time(internal::GetTimeInMillis() - start); + + // Notifies the unit test event listener that a test has just finished. + repeater->OnTestEnd(*this); + + // Tells UnitTest to stop associating assertion results to this + // test. + impl->set_current_test_info(NULL); +} + +// class TestCase + +// Gets the number of successful tests in this test case. +int TestCase::successful_test_count() const { + return CountIf(test_info_list_, TestPassed); +} + +// Gets the number of failed tests in this test case. +int TestCase::failed_test_count() const { + return CountIf(test_info_list_, TestFailed); +} + +// Gets the number of disabled tests that will be reported in the XML report. +int TestCase::reportable_disabled_test_count() const { + return CountIf(test_info_list_, TestReportableDisabled); +} + +// Gets the number of disabled tests in this test case. +int TestCase::disabled_test_count() const { + return CountIf(test_info_list_, TestDisabled); +} + +// Gets the number of tests to be printed in the XML report. +int TestCase::reportable_test_count() const { + return CountIf(test_info_list_, TestReportable); +} + +// Get the number of tests in this test case that should run. +int TestCase::test_to_run_count() const { + return CountIf(test_info_list_, ShouldRunTest); +} + +// Gets the number of all tests. +int TestCase::total_test_count() const { + return static_cast(test_info_list_.size()); +} + +// Creates a TestCase with the given name. +// +// Arguments: +// +// name: name of the test case +// a_type_param: the name of the test case's type parameter, or NULL if +// this is not a typed or a type-parameterized test case. +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +TestCase::TestCase(const char* a_name, const char* a_type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc) + : name_(a_name), + type_param_(a_type_param ? new std::string(a_type_param) : NULL), + set_up_tc_(set_up_tc), + tear_down_tc_(tear_down_tc), + should_run_(false), + elapsed_time_(0) { +} + +// Destructor of TestCase. +TestCase::~TestCase() { + // Deletes every Test in the collection. + ForEach(test_info_list_, internal::Delete); +} + +// Returns the i-th test among all the tests. i can range from 0 to +// total_test_count() - 1. If i is not in that range, returns NULL. +const TestInfo* TestCase::GetTestInfo(int i) const { + const int index = GetElementOr(test_indices_, i, -1); + return index < 0 ? NULL : test_info_list_[index]; +} + +// Returns the i-th test among all the tests. i can range from 0 to +// total_test_count() - 1. If i is not in that range, returns NULL. +TestInfo* TestCase::GetMutableTestInfo(int i) { + const int index = GetElementOr(test_indices_, i, -1); + return index < 0 ? NULL : test_info_list_[index]; +} + +// Adds a test to this test case. Will delete the test upon +// destruction of the TestCase object. +void TestCase::AddTestInfo(TestInfo * test_info) { + test_info_list_.push_back(test_info); + test_indices_.push_back(static_cast(test_indices_.size())); +} + +// Runs every test in this TestCase. +void TestCase::Run() { + if (!should_run_) return; + + internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); + impl->set_current_test_case(this); + + TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); + + repeater->OnTestCaseStart(*this); + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &TestCase::RunSetUpTestCase, "SetUpTestCase()"); + + const internal::TimeInMillis start = internal::GetTimeInMillis(); + for (int i = 0; i < total_test_count(); i++) { + GetMutableTestInfo(i)->Run(); + } + elapsed_time_ = internal::GetTimeInMillis() - start; + + impl->os_stack_trace_getter()->UponLeavingGTest(); + internal::HandleExceptionsInMethodIfSupported( + this, &TestCase::RunTearDownTestCase, "TearDownTestCase()"); + + repeater->OnTestCaseEnd(*this); + impl->set_current_test_case(NULL); +} + +// Clears the results of all tests in this test case. +void TestCase::ClearResult() { + ad_hoc_test_result_.Clear(); + ForEach(test_info_list_, TestInfo::ClearTestResult); +} + +// Shuffles the tests in this test case. +void TestCase::ShuffleTests(internal::Random* random) { + Shuffle(random, &test_indices_); +} + +// Restores the test order to before the first shuffle. +void TestCase::UnshuffleTests() { + for (size_t i = 0; i < test_indices_.size(); i++) { + test_indices_[i] = static_cast(i); + } +} + +// Formats a countable noun. Depending on its quantity, either the +// singular form or the plural form is used. e.g. +// +// FormatCountableNoun(1, "formula", "formuli") returns "1 formula". +// FormatCountableNoun(5, "book", "books") returns "5 books". +static std::string FormatCountableNoun(int count, + const char * singular_form, + const char * plural_form) { + return internal::StreamableToString(count) + " " + + (count == 1 ? singular_form : plural_form); +} + +// Formats the count of tests. +static std::string FormatTestCount(int test_count) { + return FormatCountableNoun(test_count, "test", "tests"); +} + +// Formats the count of test cases. +static std::string FormatTestCaseCount(int test_case_count) { + return FormatCountableNoun(test_case_count, "test case", "test cases"); +} + +// Converts a TestPartResult::Type enum to human-friendly string +// representation. Both kNonFatalFailure and kFatalFailure are translated +// to "Failure", as the user usually doesn't care about the difference +// between the two when viewing the test result. +static const char * TestPartResultTypeToString(TestPartResult::Type type) { + switch (type) { + case TestPartResult::kSuccess: + return "Success"; + + case TestPartResult::kNonFatalFailure: + case TestPartResult::kFatalFailure: +#ifdef _MSC_VER + return "error: "; +#else + return "Failure\n"; +#endif + default: + return "Unknown result type"; + } +} + +namespace internal { + +// Prints a TestPartResult to an std::string. +static std::string PrintTestPartResultToString( + const TestPartResult& test_part_result) { + return (Message() + << internal::FormatFileLocation(test_part_result.file_name(), + test_part_result.line_number()) + << " " << TestPartResultTypeToString(test_part_result.type()) + << test_part_result.message()).GetString(); +} + +// Prints a TestPartResult. +static void PrintTestPartResult(const TestPartResult& test_part_result) { + const std::string& result = + PrintTestPartResultToString(test_part_result); + printf("%s\n", result.c_str()); + fflush(stdout); + // If the test program runs in Visual Studio or a debugger, the + // following statements add the test part result message to the Output + // window such that the user can double-click on it to jump to the + // corresponding source code location; otherwise they do nothing. +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + // We don't call OutputDebugString*() on Windows Mobile, as printing + // to stdout is done by OutputDebugString() there already - we don't + // want the same message printed twice. + ::OutputDebugStringA(result.c_str()); + ::OutputDebugStringA("\n"); +#endif +} + +// class PrettyUnitTestResultPrinter + +enum GTestColor { + COLOR_DEFAULT, + COLOR_RED, + COLOR_GREEN, + COLOR_YELLOW +}; + +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + +// Returns the character attribute for the given color. +WORD GetColorAttribute(GTestColor color) { + switch (color) { + case COLOR_RED: return FOREGROUND_RED; + case COLOR_GREEN: return FOREGROUND_GREEN; + case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN; + default: return 0; + } +} + +#else + +// Returns the ANSI color code for the given color. COLOR_DEFAULT is +// an invalid input. +const char* GetAnsiColorCode(GTestColor color) { + switch (color) { + case COLOR_RED: return "1"; + case COLOR_GREEN: return "2"; + case COLOR_YELLOW: return "3"; + default: return NULL; + }; +} + +#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + +// Returns true iff Google Test should use colors in the output. +bool ShouldUseColor(bool stdout_is_tty) { + const char* const gtest_color = GTEST_FLAG(color).c_str(); + + if (String::CaseInsensitiveCStringEquals(gtest_color, "auto")) { +#if GTEST_OS_WINDOWS + // On Windows the TERM variable is usually not set, but the + // console there does support colors. + return stdout_is_tty; +#else + // On non-Windows platforms, we rely on the TERM variable. + const char* const term = posix::GetEnv("TERM"); + const bool term_supports_color = + String::CStringEquals(term, "xterm") || + String::CStringEquals(term, "xterm-color") || + String::CStringEquals(term, "xterm-256color") || + String::CStringEquals(term, "screen") || + String::CStringEquals(term, "screen-256color") || + String::CStringEquals(term, "linux") || + String::CStringEquals(term, "cygwin"); + return stdout_is_tty && term_supports_color; +#endif // GTEST_OS_WINDOWS + } + + return String::CaseInsensitiveCStringEquals(gtest_color, "yes") || + String::CaseInsensitiveCStringEquals(gtest_color, "true") || + String::CaseInsensitiveCStringEquals(gtest_color, "t") || + String::CStringEquals(gtest_color, "1"); + // We take "yes", "true", "t", and "1" as meaning "yes". If the + // value is neither one of these nor "auto", we treat it as "no" to + // be conservative. +} + +// Helpers for printing colored strings to stdout. Note that on Windows, we +// cannot simply emit special characters and have the terminal change colors. +// This routine must actually emit the characters rather than return a string +// that would be colored when printed, as can be done on Linux. +void ColoredPrintf(GTestColor color, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + +#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS || GTEST_OS_IOS + const bool use_color = false; +#else + static const bool in_color_mode = + ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0); + const bool use_color = in_color_mode && (color != COLOR_DEFAULT); +#endif // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS + // The '!= 0' comparison is necessary to satisfy MSVC 7.1. + + if (!use_color) { + vprintf(fmt, args); + va_end(args); + return; + } + +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); + + // Gets the current text color. + CONSOLE_SCREEN_BUFFER_INFO buffer_info; + GetConsoleScreenBufferInfo(stdout_handle, &buffer_info); + const WORD old_color_attrs = buffer_info.wAttributes; + + // We need to flush the stream buffers into the console before each + // SetConsoleTextAttribute call lest it affect the text that is already + // printed but has not yet reached the console. + fflush(stdout); + SetConsoleTextAttribute(stdout_handle, + GetColorAttribute(color) | FOREGROUND_INTENSITY); + vprintf(fmt, args); + + fflush(stdout); + // Restores the text color. + SetConsoleTextAttribute(stdout_handle, old_color_attrs); +#else + printf("\033[0;3%sm", GetAnsiColorCode(color)); + vprintf(fmt, args); + printf("\033[m"); // Resets the terminal to default. +#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE + va_end(args); +} + +// Text printed in Google Test's text output and --gunit_list_tests +// output to label the type parameter and value parameter for a test. +static const char kTypeParamLabel[] = "TypeParam"; +static const char kValueParamLabel[] = "GetParam()"; + +void PrintFullTestCommentIfPresent(const TestInfo& test_info) { + const char* const type_param = test_info.type_param(); + const char* const value_param = test_info.value_param(); + + if (type_param != NULL || value_param != NULL) { + printf(", where "); + if (type_param != NULL) { + printf("%s = %s", kTypeParamLabel, type_param); + if (value_param != NULL) + printf(" and "); + } + if (value_param != NULL) { + printf("%s = %s", kValueParamLabel, value_param); + } + } +} + +// This class implements the TestEventListener interface. +// +// Class PrettyUnitTestResultPrinter is copyable. +class PrettyUnitTestResultPrinter : public TestEventListener { + public: + PrettyUnitTestResultPrinter() {} + static void PrintTestName(const char * test_case, const char * test) { + printf("%s.%s", test_case, test); + } + + // The following methods override what's in the TestEventListener class. + virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration); + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test); + virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestCaseStart(const TestCase& test_case); + virtual void OnTestStart(const TestInfo& test_info); + virtual void OnTestPartResult(const TestPartResult& result); + virtual void OnTestEnd(const TestInfo& test_info); + virtual void OnTestCaseEnd(const TestCase& test_case); + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test); + virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} + + private: + static void PrintFailedTests(const UnitTest& unit_test); +}; + + // Fired before each iteration of tests starts. +void PrettyUnitTestResultPrinter::OnTestIterationStart( + const UnitTest& unit_test, int iteration) { + if (GTEST_FLAG(repeat) != 1) + printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration + 1); + + const char* const filter = GTEST_FLAG(filter).c_str(); + + // Prints the filter if it's not *. This reminds the user that some + // tests may be skipped. + if (!String::CStringEquals(filter, kUniversalFilter)) { + ColoredPrintf(COLOR_YELLOW, + "Note: %s filter = %s\n", GTEST_NAME_, filter); + } + + if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) { + const Int32 shard_index = Int32FromEnvOrDie(kTestShardIndex, -1); + ColoredPrintf(COLOR_YELLOW, + "Note: This is test shard %d of %s.\n", + static_cast(shard_index) + 1, + internal::posix::GetEnv(kTestTotalShards)); + } + + if (GTEST_FLAG(shuffle)) { + ColoredPrintf(COLOR_YELLOW, + "Note: Randomizing tests' orders with a seed of %d .\n", + unit_test.random_seed()); + } + + ColoredPrintf(COLOR_GREEN, "[==========] "); + printf("Running %s from %s.\n", + FormatTestCount(unit_test.test_to_run_count()).c_str(), + FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str()); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart( + const UnitTest& /*unit_test*/) { + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("Global test environment set-up.\n"); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) { + const std::string counts = + FormatCountableNoun(test_case.test_to_run_count(), "test", "tests"); + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("%s from %s", counts.c_str(), test_case.name()); + if (test_case.type_param() == NULL) { + printf("\n"); + } else { + printf(", where %s = %s\n", kTypeParamLabel, test_case.type_param()); + } + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) { + ColoredPrintf(COLOR_GREEN, "[ RUN ] "); + PrintTestName(test_info.test_case_name(), test_info.name()); + printf("\n"); + fflush(stdout); +} + +// Called after an assertion failure. +void PrettyUnitTestResultPrinter::OnTestPartResult( + const TestPartResult& result) { + // If the test part succeeded, we don't need to do anything. + if (result.type() == TestPartResult::kSuccess) + return; + + // Print failure message from the assertion (e.g. expected this and got that). + PrintTestPartResult(result); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) { + if (test_info.result()->Passed()) { + ColoredPrintf(COLOR_GREEN, "[ OK ] "); + } else { + ColoredPrintf(COLOR_RED, "[ FAILED ] "); + } + PrintTestName(test_info.test_case_name(), test_info.name()); + if (test_info.result()->Failed()) + PrintFullTestCommentIfPresent(test_info); + + if (GTEST_FLAG(print_time)) { + printf(" (%s ms)\n", internal::StreamableToString( + test_info.result()->elapsed_time()).c_str()); + } else { + printf("\n"); + } + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) { + if (!GTEST_FLAG(print_time)) return; + + const std::string counts = + FormatCountableNoun(test_case.test_to_run_count(), "test", "tests"); + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("%s from %s (%s ms total)\n\n", + counts.c_str(), test_case.name(), + internal::StreamableToString(test_case.elapsed_time()).c_str()); + fflush(stdout); +} + +void PrettyUnitTestResultPrinter::OnEnvironmentsTearDownStart( + const UnitTest& /*unit_test*/) { + ColoredPrintf(COLOR_GREEN, "[----------] "); + printf("Global test environment tear-down\n"); + fflush(stdout); +} + +// Internal helper for printing the list of failed tests. +void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) { + const int failed_test_count = unit_test.failed_test_count(); + if (failed_test_count == 0) { + return; + } + + for (int i = 0; i < unit_test.total_test_case_count(); ++i) { + const TestCase& test_case = *unit_test.GetTestCase(i); + if (!test_case.should_run() || (test_case.failed_test_count() == 0)) { + continue; + } + for (int j = 0; j < test_case.total_test_count(); ++j) { + const TestInfo& test_info = *test_case.GetTestInfo(j); + if (!test_info.should_run() || test_info.result()->Passed()) { + continue; + } + ColoredPrintf(COLOR_RED, "[ FAILED ] "); + printf("%s.%s", test_case.name(), test_info.name()); + PrintFullTestCommentIfPresent(test_info); + printf("\n"); + } + } +} + +void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, + int /*iteration*/) { + ColoredPrintf(COLOR_GREEN, "[==========] "); + printf("%s from %s ran.", + FormatTestCount(unit_test.test_to_run_count()).c_str(), + FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str()); + if (GTEST_FLAG(print_time)) { + printf(" (%s ms total)", + internal::StreamableToString(unit_test.elapsed_time()).c_str()); + } + printf("\n"); + ColoredPrintf(COLOR_GREEN, "[ PASSED ] "); + printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str()); + + int num_failures = unit_test.failed_test_count(); + if (!unit_test.Passed()) { + const int failed_test_count = unit_test.failed_test_count(); + ColoredPrintf(COLOR_RED, "[ FAILED ] "); + printf("%s, listed below:\n", FormatTestCount(failed_test_count).c_str()); + PrintFailedTests(unit_test); + printf("\n%2d FAILED %s\n", num_failures, + num_failures == 1 ? "TEST" : "TESTS"); + } + + int num_disabled = unit_test.reportable_disabled_test_count(); + if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) { + if (!num_failures) { + printf("\n"); // Add a spacer if no FAILURE banner is displayed. + } + ColoredPrintf(COLOR_YELLOW, + " YOU HAVE %d DISABLED %s\n\n", + num_disabled, + num_disabled == 1 ? "TEST" : "TESTS"); + } + // Ensure that Google Test output is printed before, e.g., heapchecker output. + fflush(stdout); +} + +// End PrettyUnitTestResultPrinter + +// class TestEventRepeater +// +// This class forwards events to other event listeners. +class TestEventRepeater : public TestEventListener { + public: + TestEventRepeater() : forwarding_enabled_(true) {} + virtual ~TestEventRepeater(); + void Append(TestEventListener *listener); + TestEventListener* Release(TestEventListener* listener); + + // Controls whether events will be forwarded to listeners_. Set to false + // in death test child processes. + bool forwarding_enabled() const { return forwarding_enabled_; } + void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; } + + virtual void OnTestProgramStart(const UnitTest& unit_test); + virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration); + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test); + virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test); + virtual void OnTestCaseStart(const TestCase& test_case); + virtual void OnTestStart(const TestInfo& test_info); + virtual void OnTestPartResult(const TestPartResult& result); + virtual void OnTestEnd(const TestInfo& test_info); + virtual void OnTestCaseEnd(const TestCase& test_case); + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test); + virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test); + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + virtual void OnTestProgramEnd(const UnitTest& unit_test); + + private: + // Controls whether events will be forwarded to listeners_. Set to false + // in death test child processes. + bool forwarding_enabled_; + // The list of listeners that receive events. + std::vector listeners_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventRepeater); +}; + +TestEventRepeater::~TestEventRepeater() { + ForEach(listeners_, Delete); +} + +void TestEventRepeater::Append(TestEventListener *listener) { + listeners_.push_back(listener); +} + +// TODO(vladl@google.com): Factor the search functionality into Vector::Find. +TestEventListener* TestEventRepeater::Release(TestEventListener *listener) { + for (size_t i = 0; i < listeners_.size(); ++i) { + if (listeners_[i] == listener) { + listeners_.erase(listeners_.begin() + i); + return listener; + } + } + + return NULL; +} + +// Since most methods are very similar, use macros to reduce boilerplate. +// This defines a member that forwards the call to all listeners. +#define GTEST_REPEATER_METHOD_(Name, Type) \ +void TestEventRepeater::Name(const Type& parameter) { \ + if (forwarding_enabled_) { \ + for (size_t i = 0; i < listeners_.size(); i++) { \ + listeners_[i]->Name(parameter); \ + } \ + } \ +} +// This defines a member that forwards the call to all listeners in reverse +// order. +#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \ +void TestEventRepeater::Name(const Type& parameter) { \ + if (forwarding_enabled_) { \ + for (int i = static_cast(listeners_.size()) - 1; i >= 0; i--) { \ + listeners_[i]->Name(parameter); \ + } \ + } \ +} + +GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest) +GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest) +GTEST_REPEATER_METHOD_(OnTestCaseStart, TestCase) +GTEST_REPEATER_METHOD_(OnTestStart, TestInfo) +GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult) +GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest) +GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo) +GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestCase) +GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest) + +#undef GTEST_REPEATER_METHOD_ +#undef GTEST_REVERSE_REPEATER_METHOD_ + +void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test, + int iteration) { + if (forwarding_enabled_) { + for (size_t i = 0; i < listeners_.size(); i++) { + listeners_[i]->OnTestIterationStart(unit_test, iteration); + } + } +} + +void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test, + int iteration) { + if (forwarding_enabled_) { + for (int i = static_cast(listeners_.size()) - 1; i >= 0; i--) { + listeners_[i]->OnTestIterationEnd(unit_test, iteration); + } + } +} + +// End TestEventRepeater + +// This class generates an XML output file. +class XmlUnitTestResultPrinter : public EmptyTestEventListener { + public: + explicit XmlUnitTestResultPrinter(const char* output_file); + + virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); + + private: + // Is c a whitespace character that is normalized to a space character + // when it appears in an XML attribute value? + static bool IsNormalizableWhitespace(char c) { + return c == 0x9 || c == 0xA || c == 0xD; + } + + // May c appear in a well-formed XML document? + static bool IsValidXmlCharacter(char c) { + return IsNormalizableWhitespace(c) || c >= 0x20; + } + + // Returns an XML-escaped copy of the input string str. If + // is_attribute is true, the text is meant to appear as an attribute + // value, and normalizable whitespace is preserved by replacing it + // with character references. + static std::string EscapeXml(const std::string& str, bool is_attribute); + + // Returns the given string with all characters invalid in XML removed. + static std::string RemoveInvalidXmlCharacters(const std::string& str); + + // Convenience wrapper around EscapeXml when str is an attribute value. + static std::string EscapeXmlAttribute(const std::string& str) { + return EscapeXml(str, true); + } + + // Convenience wrapper around EscapeXml when str is not an attribute value. + static std::string EscapeXmlText(const char* str) { + return EscapeXml(str, false); + } + + // Verifies that the given attribute belongs to the given element and + // streams the attribute as XML. + static void OutputXmlAttribute(std::ostream* stream, + const std::string& element_name, + const std::string& name, + const std::string& value); + + // Streams an XML CDATA section, escaping invalid CDATA sequences as needed. + static void OutputXmlCDataSection(::std::ostream* stream, const char* data); + + // Streams an XML representation of a TestInfo object. + static void OutputXmlTestInfo(::std::ostream* stream, + const char* test_case_name, + const TestInfo& test_info); + + // Prints an XML representation of a TestCase object + static void PrintXmlTestCase(::std::ostream* stream, + const TestCase& test_case); + + // Prints an XML summary of unit_test to output stream out. + static void PrintXmlUnitTest(::std::ostream* stream, + const UnitTest& unit_test); + + // Produces a string representing the test properties in a result as space + // delimited XML attributes based on the property key="value" pairs. + // When the std::string is not empty, it includes a space at the beginning, + // to delimit this attribute from prior attributes. + static std::string TestPropertiesAsXmlAttributes(const TestResult& result); + + // The output file. + const std::string output_file_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter); +}; + +// Creates a new XmlUnitTestResultPrinter. +XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file) + : output_file_(output_file) { + if (output_file_.c_str() == NULL || output_file_.empty()) { + fprintf(stderr, "XML output file may not be null\n"); + fflush(stderr); + exit(EXIT_FAILURE); + } +} + +// Called after the unit test ends. +void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, + int /*iteration*/) { + FILE* xmlout = NULL; + FilePath output_file(output_file_); + FilePath output_dir(output_file.RemoveFileName()); + + if (output_dir.CreateDirectoriesRecursively()) { + xmlout = posix::FOpen(output_file_.c_str(), "w"); + } + if (xmlout == NULL) { + // TODO(wan): report the reason of the failure. + // + // We don't do it for now as: + // + // 1. There is no urgent need for it. + // 2. It's a bit involved to make the errno variable thread-safe on + // all three operating systems (Linux, Windows, and Mac OS). + // 3. To interpret the meaning of errno in a thread-safe way, + // we need the strerror_r() function, which is not available on + // Windows. + fprintf(stderr, + "Unable to open file \"%s\"\n", + output_file_.c_str()); + fflush(stderr); + exit(EXIT_FAILURE); + } + std::stringstream stream; + PrintXmlUnitTest(&stream, unit_test); + fprintf(xmlout, "%s", StringStreamToString(&stream).c_str()); + fclose(xmlout); +} + +// Returns an XML-escaped copy of the input string str. If is_attribute +// is true, the text is meant to appear as an attribute value, and +// normalizable whitespace is preserved by replacing it with character +// references. +// +// Invalid XML characters in str, if any, are stripped from the output. +// It is expected that most, if not all, of the text processed by this +// module will consist of ordinary English text. +// If this module is ever modified to produce version 1.1 XML output, +// most invalid characters can be retained using character references. +// TODO(wan): It might be nice to have a minimally invasive, human-readable +// escaping scheme for invalid characters, rather than dropping them. +std::string XmlUnitTestResultPrinter::EscapeXml( + const std::string& str, bool is_attribute) { + Message m; + + for (size_t i = 0; i < str.size(); ++i) { + const char ch = str[i]; + switch (ch) { + case '<': + m << "<"; + break; + case '>': + m << ">"; + break; + case '&': + m << "&"; + break; + case '\'': + if (is_attribute) + m << "'"; + else + m << '\''; + break; + case '"': + if (is_attribute) + m << """; + else + m << '"'; + break; + default: + if (IsValidXmlCharacter(ch)) { + if (is_attribute && IsNormalizableWhitespace(ch)) + m << "&#x" << String::FormatByte(static_cast(ch)) + << ";"; + else + m << ch; + } + break; + } + } + + return m.GetString(); +} + +// Returns the given string with all characters invalid in XML removed. +// Currently invalid characters are dropped from the string. An +// alternative is to replace them with certain characters such as . or ?. +std::string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters( + const std::string& str) { + std::string output; + output.reserve(str.size()); + for (std::string::const_iterator it = str.begin(); it != str.end(); ++it) + if (IsValidXmlCharacter(*it)) + output.push_back(*it); + + return output; +} + +// The following routines generate an XML representation of a UnitTest +// object. +// +// This is how Google Test concepts map to the DTD: +// +// <-- corresponds to a UnitTest object +// <-- corresponds to a TestCase object +// <-- corresponds to a TestInfo object +// ... +// ... +// ... +// <-- individual assertion failures +// +// +// + +// Formats the given time in milliseconds as seconds. +std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) { + ::std::stringstream ss; + ss << ms/1000.0; + return ss.str(); +} + +// Converts the given epoch time in milliseconds to a date string in the ISO +// 8601 format, without the timezone information. +std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms) { + // Using non-reentrant version as localtime_r is not portable. + time_t seconds = static_cast(ms / 1000); +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4996) // Temporarily disables warning 4996 + // (function or variable may be unsafe). + const struct tm* const time_struct = localtime(&seconds); // NOLINT +# pragma warning(pop) // Restores the warning state again. +#else + const struct tm* const time_struct = localtime(&seconds); // NOLINT +#endif + if (time_struct == NULL) + return ""; // Invalid ms value + + // YYYY-MM-DDThh:mm:ss + return StreamableToString(time_struct->tm_year + 1900) + "-" + + String::FormatIntWidth2(time_struct->tm_mon + 1) + "-" + + String::FormatIntWidth2(time_struct->tm_mday) + "T" + + String::FormatIntWidth2(time_struct->tm_hour) + ":" + + String::FormatIntWidth2(time_struct->tm_min) + ":" + + String::FormatIntWidth2(time_struct->tm_sec); +} + +// Streams an XML CDATA section, escaping invalid CDATA sequences as needed. +void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream, + const char* data) { + const char* segment = data; + *stream << ""); + if (next_segment != NULL) { + stream->write( + segment, static_cast(next_segment - segment)); + *stream << "]]>]]>"); + } else { + *stream << segment; + break; + } + } + *stream << "]]>"; +} + +void XmlUnitTestResultPrinter::OutputXmlAttribute( + std::ostream* stream, + const std::string& element_name, + const std::string& name, + const std::string& value) { + const std::vector& allowed_names = + GetReservedAttributesForElement(element_name); + + GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) != + allowed_names.end()) + << "Attribute " << name << " is not allowed for element <" << element_name + << ">."; + + *stream << " " << name << "=\"" << EscapeXmlAttribute(value) << "\""; +} + +// Prints an XML representation of a TestInfo object. +// TODO(wan): There is also value in printing properties with the plain printer. +void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream, + const char* test_case_name, + const TestInfo& test_info) { + const TestResult& result = *test_info.result(); + const std::string kTestcase = "testcase"; + + *stream << " \n"; + } + const string location = internal::FormatCompilerIndependentFileLocation( + part.file_name(), part.line_number()); + const string summary = location + "\n" + part.summary(); + *stream << " "; + const string detail = location + "\n" + part.message(); + OutputXmlCDataSection(stream, RemoveInvalidXmlCharacters(detail).c_str()); + *stream << "\n"; + } + } + + if (failures == 0) + *stream << " />\n"; + else + *stream << " \n"; +} + +// Prints an XML representation of a TestCase object +void XmlUnitTestResultPrinter::PrintXmlTestCase(std::ostream* stream, + const TestCase& test_case) { + const std::string kTestsuite = "testsuite"; + *stream << " <" << kTestsuite; + OutputXmlAttribute(stream, kTestsuite, "name", test_case.name()); + OutputXmlAttribute(stream, kTestsuite, "tests", + StreamableToString(test_case.reportable_test_count())); + OutputXmlAttribute(stream, kTestsuite, "failures", + StreamableToString(test_case.failed_test_count())); + OutputXmlAttribute( + stream, kTestsuite, "disabled", + StreamableToString(test_case.reportable_disabled_test_count())); + OutputXmlAttribute(stream, kTestsuite, "errors", "0"); + OutputXmlAttribute(stream, kTestsuite, "time", + FormatTimeInMillisAsSeconds(test_case.elapsed_time())); + *stream << TestPropertiesAsXmlAttributes(test_case.ad_hoc_test_result()) + << ">\n"; + + for (int i = 0; i < test_case.total_test_count(); ++i) { + if (test_case.GetTestInfo(i)->is_reportable()) + OutputXmlTestInfo(stream, test_case.name(), *test_case.GetTestInfo(i)); + } + *stream << " \n"; +} + +// Prints an XML summary of unit_test to output stream out. +void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream, + const UnitTest& unit_test) { + const std::string kTestsuites = "testsuites"; + + *stream << "\n"; + *stream << "<" << kTestsuites; + + OutputXmlAttribute(stream, kTestsuites, "tests", + StreamableToString(unit_test.reportable_test_count())); + OutputXmlAttribute(stream, kTestsuites, "failures", + StreamableToString(unit_test.failed_test_count())); + OutputXmlAttribute( + stream, kTestsuites, "disabled", + StreamableToString(unit_test.reportable_disabled_test_count())); + OutputXmlAttribute(stream, kTestsuites, "errors", "0"); + OutputXmlAttribute( + stream, kTestsuites, "timestamp", + FormatEpochTimeInMillisAsIso8601(unit_test.start_timestamp())); + OutputXmlAttribute(stream, kTestsuites, "time", + FormatTimeInMillisAsSeconds(unit_test.elapsed_time())); + + if (GTEST_FLAG(shuffle)) { + OutputXmlAttribute(stream, kTestsuites, "random_seed", + StreamableToString(unit_test.random_seed())); + } + + *stream << TestPropertiesAsXmlAttributes(unit_test.ad_hoc_test_result()); + + OutputXmlAttribute(stream, kTestsuites, "name", "AllTests"); + *stream << ">\n"; + + for (int i = 0; i < unit_test.total_test_case_count(); ++i) { + if (unit_test.GetTestCase(i)->reportable_test_count() > 0) + PrintXmlTestCase(stream, *unit_test.GetTestCase(i)); + } + *stream << "\n"; +} + +// Produces a string representing the test properties in a result as space +// delimited XML attributes based on the property key="value" pairs. +std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes( + const TestResult& result) { + Message attributes; + for (int i = 0; i < result.test_property_count(); ++i) { + const TestProperty& property = result.GetTestProperty(i); + attributes << " " << property.key() << "=" + << "\"" << EscapeXmlAttribute(property.value()) << "\""; + } + return attributes.GetString(); +} + +// End XmlUnitTestResultPrinter + +#if GTEST_CAN_STREAM_RESULTS_ + +// Checks if str contains '=', '&', '%' or '\n' characters. If yes, +// replaces them by "%xx" where xx is their hexadecimal value. For +// example, replaces "=" with "%3D". This algorithm is O(strlen(str)) +// in both time and space -- important as the input str may contain an +// arbitrarily long test failure message and stack trace. +string StreamingListener::UrlEncode(const char* str) { + string result; + result.reserve(strlen(str) + 1); + for (char ch = *str; ch != '\0'; ch = *++str) { + switch (ch) { + case '%': + case '=': + case '&': + case '\n': + result.append("%" + String::FormatByte(static_cast(ch))); + break; + default: + result.push_back(ch); + break; + } + } + return result; +} + +void StreamingListener::SocketWriter::MakeConnection() { + GTEST_CHECK_(sockfd_ == -1) + << "MakeConnection() can't be called when there is already a connection."; + + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; // To allow both IPv4 and IPv6 addresses. + hints.ai_socktype = SOCK_STREAM; + addrinfo* servinfo = NULL; + + // Use the getaddrinfo() to get a linked list of IP addresses for + // the given host name. + const int error_num = getaddrinfo( + host_name_.c_str(), port_num_.c_str(), &hints, &servinfo); + if (error_num != 0) { + GTEST_LOG_(WARNING) << "stream_result_to: getaddrinfo() failed: " + << gai_strerror(error_num); + } + + // Loop through all the results and connect to the first we can. + for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != NULL; + cur_addr = cur_addr->ai_next) { + sockfd_ = socket( + cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol); + if (sockfd_ != -1) { + // Connect the client socket to the server socket. + if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) { + close(sockfd_); + sockfd_ = -1; + } + } + } + + freeaddrinfo(servinfo); // all done with this structure + + if (sockfd_ == -1) { + GTEST_LOG_(WARNING) << "stream_result_to: failed to connect to " + << host_name_ << ":" << port_num_; + } +} + +// End of class Streaming Listener +#endif // GTEST_CAN_STREAM_RESULTS__ + +// Class ScopedTrace + +// Pushes the given source file location and message onto a per-thread +// trace stack maintained by Google Test. +ScopedTrace::ScopedTrace(const char* file, int line, const Message& message) + GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) { + TraceInfo trace; + trace.file = file; + trace.line = line; + trace.message = message.GetString(); + + UnitTest::GetInstance()->PushGTestTrace(trace); +} + +// Pops the info pushed by the c'tor. +ScopedTrace::~ScopedTrace() + GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) { + UnitTest::GetInstance()->PopGTestTrace(); +} + + +// class OsStackTraceGetter + +// Returns the current OS stack trace as an std::string. Parameters: +// +// max_depth - the maximum number of stack frames to be included +// in the trace. +// skip_count - the number of top frames to be skipped; doesn't count +// against max_depth. +// +string OsStackTraceGetter::CurrentStackTrace(int /* max_depth */, + int /* skip_count */) + GTEST_LOCK_EXCLUDED_(mutex_) { + return ""; +} + +void OsStackTraceGetter::UponLeavingGTest() + GTEST_LOCK_EXCLUDED_(mutex_) { +} + +const char* const +OsStackTraceGetter::kElidedFramesMarker = + "... " GTEST_NAME_ " internal frames ..."; + +// A helper class that creates the premature-exit file in its +// constructor and deletes the file in its destructor. +class ScopedPrematureExitFile { + public: + explicit ScopedPrematureExitFile(const char* premature_exit_filepath) + : premature_exit_filepath_(premature_exit_filepath) { + // If a path to the premature-exit file is specified... + if (premature_exit_filepath != NULL && *premature_exit_filepath != '\0') { + // create the file with a single "0" character in it. I/O + // errors are ignored as there's nothing better we can do and we + // don't want to fail the test because of this. + FILE* pfile = posix::FOpen(premature_exit_filepath, "w"); + fwrite("0", 1, 1, pfile); + fclose(pfile); + } + } + + ~ScopedPrematureExitFile() { + if (premature_exit_filepath_ != NULL && *premature_exit_filepath_ != '\0') { + remove(premature_exit_filepath_); + } + } + + private: + const char* const premature_exit_filepath_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedPrematureExitFile); +}; + +} // namespace internal + +// class TestEventListeners + +TestEventListeners::TestEventListeners() + : repeater_(new internal::TestEventRepeater()), + default_result_printer_(NULL), + default_xml_generator_(NULL) { +} + +TestEventListeners::~TestEventListeners() { delete repeater_; } + +// Returns the standard listener responsible for the default console +// output. Can be removed from the listeners list to shut down default +// console output. Note that removing this object from the listener list +// with Release transfers its ownership to the user. +void TestEventListeners::Append(TestEventListener* listener) { + repeater_->Append(listener); +} + +// Removes the given event listener from the list and returns it. It then +// becomes the caller's responsibility to delete the listener. Returns +// NULL if the listener is not found in the list. +TestEventListener* TestEventListeners::Release(TestEventListener* listener) { + if (listener == default_result_printer_) + default_result_printer_ = NULL; + else if (listener == default_xml_generator_) + default_xml_generator_ = NULL; + return repeater_->Release(listener); +} + +// Returns repeater that broadcasts the TestEventListener events to all +// subscribers. +TestEventListener* TestEventListeners::repeater() { return repeater_; } + +// Sets the default_result_printer attribute to the provided listener. +// The listener is also added to the listener list and previous +// default_result_printer is removed from it and deleted. The listener can +// also be NULL in which case it will not be added to the list. Does +// nothing if the previous and the current listener objects are the same. +void TestEventListeners::SetDefaultResultPrinter(TestEventListener* listener) { + if (default_result_printer_ != listener) { + // It is an error to pass this method a listener that is already in the + // list. + delete Release(default_result_printer_); + default_result_printer_ = listener; + if (listener != NULL) + Append(listener); + } +} + +// Sets the default_xml_generator attribute to the provided listener. The +// listener is also added to the listener list and previous +// default_xml_generator is removed from it and deleted. The listener can +// also be NULL in which case it will not be added to the list. Does +// nothing if the previous and the current listener objects are the same. +void TestEventListeners::SetDefaultXmlGenerator(TestEventListener* listener) { + if (default_xml_generator_ != listener) { + // It is an error to pass this method a listener that is already in the + // list. + delete Release(default_xml_generator_); + default_xml_generator_ = listener; + if (listener != NULL) + Append(listener); + } +} + +// Controls whether events will be forwarded by the repeater to the +// listeners in the list. +bool TestEventListeners::EventForwardingEnabled() const { + return repeater_->forwarding_enabled(); +} + +void TestEventListeners::SuppressEventForwarding() { + repeater_->set_forwarding_enabled(false); +} + +// class UnitTest + +// Gets the singleton UnitTest object. The first time this method is +// called, a UnitTest object is constructed and returned. Consecutive +// calls will return the same object. +// +// We don't protect this under mutex_ as a user is not supposed to +// call this before main() starts, from which point on the return +// value will never change. +UnitTest* UnitTest::GetInstance() { + // When compiled with MSVC 7.1 in optimized mode, destroying the + // UnitTest object upon exiting the program messes up the exit code, + // causing successful tests to appear failed. We have to use a + // different implementation in this case to bypass the compiler bug. + // This implementation makes the compiler happy, at the cost of + // leaking the UnitTest object. + + // CodeGear C++Builder insists on a public destructor for the + // default implementation. Use this implementation to keep good OO + // design with private destructor. + +#if (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__) + static UnitTest* const instance = new UnitTest; + return instance; +#else + static UnitTest instance; + return &instance; +#endif // (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__) +} + +// Gets the number of successful test cases. +int UnitTest::successful_test_case_count() const { + return impl()->successful_test_case_count(); +} + +// Gets the number of failed test cases. +int UnitTest::failed_test_case_count() const { + return impl()->failed_test_case_count(); +} + +// Gets the number of all test cases. +int UnitTest::total_test_case_count() const { + return impl()->total_test_case_count(); +} + +// Gets the number of all test cases that contain at least one test +// that should run. +int UnitTest::test_case_to_run_count() const { + return impl()->test_case_to_run_count(); +} + +// Gets the number of successful tests. +int UnitTest::successful_test_count() const { + return impl()->successful_test_count(); +} + +// Gets the number of failed tests. +int UnitTest::failed_test_count() const { return impl()->failed_test_count(); } + +// Gets the number of disabled tests that will be reported in the XML report. +int UnitTest::reportable_disabled_test_count() const { + return impl()->reportable_disabled_test_count(); +} + +// Gets the number of disabled tests. +int UnitTest::disabled_test_count() const { + return impl()->disabled_test_count(); +} + +// Gets the number of tests to be printed in the XML report. +int UnitTest::reportable_test_count() const { + return impl()->reportable_test_count(); +} + +// Gets the number of all tests. +int UnitTest::total_test_count() const { return impl()->total_test_count(); } + +// Gets the number of tests that should run. +int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); } + +// Gets the time of the test program start, in ms from the start of the +// UNIX epoch. +internal::TimeInMillis UnitTest::start_timestamp() const { + return impl()->start_timestamp(); +} + +// Gets the elapsed time, in milliseconds. +internal::TimeInMillis UnitTest::elapsed_time() const { + return impl()->elapsed_time(); +} + +// Returns true iff the unit test passed (i.e. all test cases passed). +bool UnitTest::Passed() const { return impl()->Passed(); } + +// Returns true iff the unit test failed (i.e. some test case failed +// or something outside of all tests failed). +bool UnitTest::Failed() const { return impl()->Failed(); } + +// Gets the i-th test case among all the test cases. i can range from 0 to +// total_test_case_count() - 1. If i is not in that range, returns NULL. +const TestCase* UnitTest::GetTestCase(int i) const { + return impl()->GetTestCase(i); +} + +// Returns the TestResult containing information on test failures and +// properties logged outside of individual test cases. +const TestResult& UnitTest::ad_hoc_test_result() const { + return *impl()->ad_hoc_test_result(); +} + +// Gets the i-th test case among all the test cases. i can range from 0 to +// total_test_case_count() - 1. If i is not in that range, returns NULL. +TestCase* UnitTest::GetMutableTestCase(int i) { + return impl()->GetMutableTestCase(i); +} + +// Returns the list of event listeners that can be used to track events +// inside Google Test. +TestEventListeners& UnitTest::listeners() { + return *impl()->listeners(); +} + +// Registers and returns a global test environment. When a test +// program is run, all global test environments will be set-up in the +// order they were registered. After all tests in the program have +// finished, all global test environments will be torn-down in the +// *reverse* order they were registered. +// +// The UnitTest object takes ownership of the given environment. +// +// We don't protect this under mutex_, as we only support calling it +// from the main thread. +Environment* UnitTest::AddEnvironment(Environment* env) { + if (env == NULL) { + return NULL; + } + + impl_->environments().push_back(env); + return env; +} + +// Adds a TestPartResult to the current TestResult object. All Google Test +// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call +// this to report their results. The user code should use the +// assertion macros instead of calling this directly. +void UnitTest::AddTestPartResult( + TestPartResult::Type result_type, + const char* file_name, + int line_number, + const std::string& message, + const std::string& os_stack_trace) GTEST_LOCK_EXCLUDED_(mutex_) { + Message msg; + msg << message; + + internal::MutexLock lock(&mutex_); + if (impl_->gtest_trace_stack().size() > 0) { + msg << "\n" << GTEST_NAME_ << " trace:"; + + for (int i = static_cast(impl_->gtest_trace_stack().size()); + i > 0; --i) { + const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1]; + msg << "\n" << internal::FormatFileLocation(trace.file, trace.line) + << " " << trace.message; + } + } + + if (os_stack_trace.c_str() != NULL && !os_stack_trace.empty()) { + msg << internal::kStackTraceMarker << os_stack_trace; + } + + const TestPartResult result = + TestPartResult(result_type, file_name, line_number, + msg.GetString().c_str()); + impl_->GetTestPartResultReporterForCurrentThread()-> + ReportTestPartResult(result); + + if (result_type != TestPartResult::kSuccess) { + // gtest_break_on_failure takes precedence over + // gtest_throw_on_failure. This allows a user to set the latter + // in the code (perhaps in order to use Google Test assertions + // with another testing framework) and specify the former on the + // command line for debugging. + if (GTEST_FLAG(break_on_failure)) { +#if GTEST_OS_WINDOWS + // Using DebugBreak on Windows allows gtest to still break into a debugger + // when a failure happens and both the --gtest_break_on_failure and + // the --gtest_catch_exceptions flags are specified. + DebugBreak(); +#else + // Dereference NULL through a volatile pointer to prevent the compiler + // from removing. We use this rather than abort() or __builtin_trap() for + // portability: Symbian doesn't implement abort() well, and some debuggers + // don't correctly trap abort(). + *static_cast(NULL) = 1; +#endif // GTEST_OS_WINDOWS + } else if (GTEST_FLAG(throw_on_failure)) { +#if GTEST_HAS_EXCEPTIONS + throw internal::GoogleTestFailureException(result); +#else + // We cannot call abort() as it generates a pop-up in debug mode + // that cannot be suppressed in VC 7.1 or below. + exit(1); +#endif + } + } +} + +// Adds a TestProperty to the current TestResult object when invoked from +// inside a test, to current TestCase's ad_hoc_test_result_ when invoked +// from SetUpTestCase or TearDownTestCase, or to the global property set +// when invoked elsewhere. If the result already contains a property with +// the same key, the value will be updated. +void UnitTest::RecordProperty(const std::string& key, + const std::string& value) { + impl_->RecordProperty(TestProperty(key, value)); +} + +// Runs all tests in this UnitTest object and prints the result. +// Returns 0 if successful, or 1 otherwise. +// +// We don't protect this under mutex_, as we only support calling it +// from the main thread. +int UnitTest::Run() { + const bool in_death_test_child_process = + internal::GTEST_FLAG(internal_run_death_test).length() > 0; + + // Google Test implements this protocol for catching that a test + // program exits before returning control to Google Test: + // + // 1. Upon start, Google Test creates a file whose absolute path + // is specified by the environment variable + // TEST_PREMATURE_EXIT_FILE. + // 2. When Google Test has finished its work, it deletes the file. + // + // This allows a test runner to set TEST_PREMATURE_EXIT_FILE before + // running a Google-Test-based test program and check the existence + // of the file at the end of the test execution to see if it has + // exited prematurely. + + // If we are in the child process of a death test, don't + // create/delete the premature exit file, as doing so is unnecessary + // and will confuse the parent process. Otherwise, create/delete + // the file upon entering/leaving this function. If the program + // somehow exits before this function has a chance to return, the + // premature-exit file will be left undeleted, causing a test runner + // that understands the premature-exit-file protocol to report the + // test as having failed. + const internal::ScopedPrematureExitFile premature_exit_file( + in_death_test_child_process ? + NULL : internal::posix::GetEnv("TEST_PREMATURE_EXIT_FILE")); + + // Captures the value of GTEST_FLAG(catch_exceptions). This value will be + // used for the duration of the program. + impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions)); + +#if GTEST_HAS_SEH + // Either the user wants Google Test to catch exceptions thrown by the + // tests or this is executing in the context of death test child + // process. In either case the user does not want to see pop-up dialogs + // about crashes - they are expected. + if (impl()->catch_exceptions() || in_death_test_child_process) { +# if !GTEST_OS_WINDOWS_MOBILE + // SetErrorMode doesn't exist on CE. + SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | + SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); +# endif // !GTEST_OS_WINDOWS_MOBILE + +# if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE + // Death test children can be terminated with _abort(). On Windows, + // _abort() can show a dialog with a warning message. This forces the + // abort message to go to stderr instead. + _set_error_mode(_OUT_TO_STDERR); +# endif + +# if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE + // In the debug version, Visual Studio pops up a separate dialog + // offering a choice to debug the aborted program. We need to suppress + // this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement + // executed. Google Test will notify the user of any unexpected + // failure via stderr. + // + // VC++ doesn't define _set_abort_behavior() prior to the version 8.0. + // Users of prior VC versions shall suffer the agony and pain of + // clicking through the countless debug dialogs. + // TODO(vladl@google.com): find a way to suppress the abort dialog() in the + // debug mode when compiled with VC 7.1 or lower. + if (!GTEST_FLAG(break_on_failure)) + _set_abort_behavior( + 0x0, // Clear the following flags: + _WRITE_ABORT_MSG | _CALL_REPORTFAULT); // pop-up window, core dump. +# endif + } +#endif // GTEST_HAS_SEH + + return internal::HandleExceptionsInMethodIfSupported( + impl(), + &internal::UnitTestImpl::RunAllTests, + "auxiliary test code (environments or event listeners)") ? 0 : 1; +} + +// Returns the working directory when the first TEST() or TEST_F() was +// executed. +const char* UnitTest::original_working_dir() const { + return impl_->original_working_dir_.c_str(); +} + +// Returns the TestCase object for the test that's currently running, +// or NULL if no test is running. +const TestCase* UnitTest::current_test_case() const + GTEST_LOCK_EXCLUDED_(mutex_) { + internal::MutexLock lock(&mutex_); + return impl_->current_test_case(); +} + +// Returns the TestInfo object for the test that's currently running, +// or NULL if no test is running. +const TestInfo* UnitTest::current_test_info() const + GTEST_LOCK_EXCLUDED_(mutex_) { + internal::MutexLock lock(&mutex_); + return impl_->current_test_info(); +} + +// Returns the random seed used at the start of the current test run. +int UnitTest::random_seed() const { return impl_->random_seed(); } + +#if GTEST_HAS_PARAM_TEST +// Returns ParameterizedTestCaseRegistry object used to keep track of +// value-parameterized tests and instantiate and register them. +internal::ParameterizedTestCaseRegistry& + UnitTest::parameterized_test_registry() + GTEST_LOCK_EXCLUDED_(mutex_) { + return impl_->parameterized_test_registry(); +} +#endif // GTEST_HAS_PARAM_TEST + +// Creates an empty UnitTest. +UnitTest::UnitTest() { + impl_ = new internal::UnitTestImpl(this); +} + +// Destructor of UnitTest. +UnitTest::~UnitTest() { + delete impl_; +} + +// Pushes a trace defined by SCOPED_TRACE() on to the per-thread +// Google Test trace stack. +void UnitTest::PushGTestTrace(const internal::TraceInfo& trace) + GTEST_LOCK_EXCLUDED_(mutex_) { + internal::MutexLock lock(&mutex_); + impl_->gtest_trace_stack().push_back(trace); +} + +// Pops a trace from the per-thread Google Test trace stack. +void UnitTest::PopGTestTrace() + GTEST_LOCK_EXCLUDED_(mutex_) { + internal::MutexLock lock(&mutex_); + impl_->gtest_trace_stack().pop_back(); +} + +namespace internal { + +UnitTestImpl::UnitTestImpl(UnitTest* parent) + : parent_(parent), +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4355) // Temporarily disables warning 4355 + // (using this in initializer). + default_global_test_part_result_reporter_(this), + default_per_thread_test_part_result_reporter_(this), +# pragma warning(pop) // Restores the warning state again. +#else + default_global_test_part_result_reporter_(this), + default_per_thread_test_part_result_reporter_(this), +#endif // _MSC_VER + global_test_part_result_repoter_( + &default_global_test_part_result_reporter_), + per_thread_test_part_result_reporter_( + &default_per_thread_test_part_result_reporter_), +#if GTEST_HAS_PARAM_TEST + parameterized_test_registry_(), + parameterized_tests_registered_(false), +#endif // GTEST_HAS_PARAM_TEST + last_death_test_case_(-1), + current_test_case_(NULL), + current_test_info_(NULL), + ad_hoc_test_result_(), + os_stack_trace_getter_(NULL), + post_flag_parse_init_performed_(false), + random_seed_(0), // Will be overridden by the flag before first use. + random_(0), // Will be reseeded before first use. + start_timestamp_(0), + elapsed_time_(0), +#if GTEST_HAS_DEATH_TEST + death_test_factory_(new DefaultDeathTestFactory), +#endif + // Will be overridden by the flag before first use. + catch_exceptions_(false) { + listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter); +} + +UnitTestImpl::~UnitTestImpl() { + // Deletes every TestCase. + ForEach(test_cases_, internal::Delete); + + // Deletes every Environment. + ForEach(environments_, internal::Delete); + + delete os_stack_trace_getter_; +} + +// Adds a TestProperty to the current TestResult object when invoked in a +// context of a test, to current test case's ad_hoc_test_result when invoke +// from SetUpTestCase/TearDownTestCase, or to the global property set +// otherwise. If the result already contains a property with the same key, +// the value will be updated. +void UnitTestImpl::RecordProperty(const TestProperty& test_property) { + std::string xml_element; + TestResult* test_result; // TestResult appropriate for property recording. + + if (current_test_info_ != NULL) { + xml_element = "testcase"; + test_result = &(current_test_info_->result_); + } else if (current_test_case_ != NULL) { + xml_element = "testsuite"; + test_result = &(current_test_case_->ad_hoc_test_result_); + } else { + xml_element = "testsuites"; + test_result = &ad_hoc_test_result_; + } + test_result->RecordProperty(xml_element, test_property); +} + +#if GTEST_HAS_DEATH_TEST +// Disables event forwarding if the control is currently in a death test +// subprocess. Must not be called before InitGoogleTest. +void UnitTestImpl::SuppressTestEventsIfInSubprocess() { + if (internal_run_death_test_flag_.get() != NULL) + listeners()->SuppressEventForwarding(); +} +#endif // GTEST_HAS_DEATH_TEST + +// Initializes event listeners performing XML output as specified by +// UnitTestOptions. Must not be called before InitGoogleTest. +void UnitTestImpl::ConfigureXmlOutput() { + const std::string& output_format = UnitTestOptions::GetOutputFormat(); + if (output_format == "xml") { + listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter( + UnitTestOptions::GetAbsolutePathToOutputFile().c_str())); + } else if (output_format != "") { + printf("WARNING: unrecognized output format \"%s\" ignored.\n", + output_format.c_str()); + fflush(stdout); + } +} + +#if GTEST_CAN_STREAM_RESULTS_ +// Initializes event listeners for streaming test results in string form. +// Must not be called before InitGoogleTest. +void UnitTestImpl::ConfigureStreamingOutput() { + const std::string& target = GTEST_FLAG(stream_result_to); + if (!target.empty()) { + const size_t pos = target.find(':'); + if (pos != std::string::npos) { + listeners()->Append(new StreamingListener(target.substr(0, pos), + target.substr(pos+1))); + } else { + printf("WARNING: unrecognized streaming target \"%s\" ignored.\n", + target.c_str()); + fflush(stdout); + } + } +} +#endif // GTEST_CAN_STREAM_RESULTS_ + +// Performs initialization dependent upon flag values obtained in +// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to +// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest +// this function is also called from RunAllTests. Since this function can be +// called more than once, it has to be idempotent. +void UnitTestImpl::PostFlagParsingInit() { + // Ensures that this function does not execute more than once. + if (!post_flag_parse_init_performed_) { + post_flag_parse_init_performed_ = true; + +#if GTEST_HAS_DEATH_TEST + InitDeathTestSubprocessControlInfo(); + SuppressTestEventsIfInSubprocess(); +#endif // GTEST_HAS_DEATH_TEST + + // Registers parameterized tests. This makes parameterized tests + // available to the UnitTest reflection API without running + // RUN_ALL_TESTS. + RegisterParameterizedTests(); + + // Configures listeners for XML output. This makes it possible for users + // to shut down the default XML output before invoking RUN_ALL_TESTS. + ConfigureXmlOutput(); + +#if GTEST_CAN_STREAM_RESULTS_ + // Configures listeners for streaming test results to the specified server. + ConfigureStreamingOutput(); +#endif // GTEST_CAN_STREAM_RESULTS_ + } +} + +// A predicate that checks the name of a TestCase against a known +// value. +// +// This is used for implementation of the UnitTest class only. We put +// it in the anonymous namespace to prevent polluting the outer +// namespace. +// +// TestCaseNameIs is copyable. +class TestCaseNameIs { + public: + // Constructor. + explicit TestCaseNameIs(const std::string& name) + : name_(name) {} + + // Returns true iff the name of test_case matches name_. + bool operator()(const TestCase* test_case) const { + return test_case != NULL && strcmp(test_case->name(), name_.c_str()) == 0; + } + + private: + std::string name_; +}; + +// Finds and returns a TestCase with the given name. If one doesn't +// exist, creates one and returns it. It's the CALLER'S +// RESPONSIBILITY to ensure that this function is only called WHEN THE +// TESTS ARE NOT SHUFFLED. +// +// Arguments: +// +// test_case_name: name of the test case +// type_param: the name of the test case's type parameter, or NULL if +// this is not a typed or a type-parameterized test case. +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +TestCase* UnitTestImpl::GetTestCase(const char* test_case_name, + const char* type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc) { + // Can we find a TestCase with the given name? + const std::vector::const_iterator test_case = + std::find_if(test_cases_.begin(), test_cases_.end(), + TestCaseNameIs(test_case_name)); + + if (test_case != test_cases_.end()) + return *test_case; + + // No. Let's create one. + TestCase* const new_test_case = + new TestCase(test_case_name, type_param, set_up_tc, tear_down_tc); + + // Is this a death test case? + if (internal::UnitTestOptions::MatchesFilter(test_case_name, + kDeathTestCaseFilter)) { + // Yes. Inserts the test case after the last death test case + // defined so far. This only works when the test cases haven't + // been shuffled. Otherwise we may end up running a death test + // after a non-death test. + ++last_death_test_case_; + test_cases_.insert(test_cases_.begin() + last_death_test_case_, + new_test_case); + } else { + // No. Appends to the end of the list. + test_cases_.push_back(new_test_case); + } + + test_case_indices_.push_back(static_cast(test_case_indices_.size())); + return new_test_case; +} + +// Helpers for setting up / tearing down the given environment. They +// are for use in the ForEach() function. +static void SetUpEnvironment(Environment* env) { env->SetUp(); } +static void TearDownEnvironment(Environment* env) { env->TearDown(); } + +// Runs all tests in this UnitTest object, prints the result, and +// returns true if all tests are successful. If any exception is +// thrown during a test, the test is considered to be failed, but the +// rest of the tests will still be run. +// +// When parameterized tests are enabled, it expands and registers +// parameterized tests first in RegisterParameterizedTests(). +// All other functions called from RunAllTests() may safely assume that +// parameterized tests are ready to be counted and run. +bool UnitTestImpl::RunAllTests() { + // Makes sure InitGoogleTest() was called. + if (!GTestIsInitialized()) { + printf("%s", + "\nThis test program did NOT call ::testing::InitGoogleTest " + "before calling RUN_ALL_TESTS(). Please fix it.\n"); + return false; + } + + // Do not run any test if the --help flag was specified. + if (g_help_flag) + return true; + + // Repeats the call to the post-flag parsing initialization in case the + // user didn't call InitGoogleTest. + PostFlagParsingInit(); + + // Even if sharding is not on, test runners may want to use the + // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding + // protocol. + internal::WriteToShardStatusFileIfNeeded(); + + // True iff we are in a subprocess for running a thread-safe-style + // death test. + bool in_subprocess_for_death_test = false; + +#if GTEST_HAS_DEATH_TEST + in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL); +#endif // GTEST_HAS_DEATH_TEST + + const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex, + in_subprocess_for_death_test); + + // Compares the full test names with the filter to decide which + // tests to run. + const bool has_tests_to_run = FilterTests(should_shard + ? HONOR_SHARDING_PROTOCOL + : IGNORE_SHARDING_PROTOCOL) > 0; + + // Lists the tests and exits if the --gtest_list_tests flag was specified. + if (GTEST_FLAG(list_tests)) { + // This must be called *after* FilterTests() has been called. + ListTestsMatchingFilter(); + return true; + } + + random_seed_ = GTEST_FLAG(shuffle) ? + GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0; + + // True iff at least one test has failed. + bool failed = false; + + TestEventListener* repeater = listeners()->repeater(); + + start_timestamp_ = GetTimeInMillis(); + repeater->OnTestProgramStart(*parent_); + + // How many times to repeat the tests? We don't want to repeat them + // when we are inside the subprocess of a death test. + const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat); + // Repeats forever if the repeat count is negative. + const bool forever = repeat < 0; + for (int i = 0; forever || i != repeat; i++) { + // We want to preserve failures generated by ad-hoc test + // assertions executed before RUN_ALL_TESTS(). + ClearNonAdHocTestResult(); + + const TimeInMillis start = GetTimeInMillis(); + + // Shuffles test cases and tests if requested. + if (has_tests_to_run && GTEST_FLAG(shuffle)) { + random()->Reseed(random_seed_); + // This should be done before calling OnTestIterationStart(), + // such that a test event listener can see the actual test order + // in the event. + ShuffleTests(); + } + + // Tells the unit test event listeners that the tests are about to start. + repeater->OnTestIterationStart(*parent_, i); + + // Runs each test case if there is at least one test to run. + if (has_tests_to_run) { + // Sets up all environments beforehand. + repeater->OnEnvironmentsSetUpStart(*parent_); + ForEach(environments_, SetUpEnvironment); + repeater->OnEnvironmentsSetUpEnd(*parent_); + + // Runs the tests only if there was no fatal failure during global + // set-up. + if (!Test::HasFatalFailure()) { + for (int test_index = 0; test_index < total_test_case_count(); + test_index++) { + GetMutableTestCase(test_index)->Run(); + } + } + + // Tears down all environments in reverse order afterwards. + repeater->OnEnvironmentsTearDownStart(*parent_); + std::for_each(environments_.rbegin(), environments_.rend(), + TearDownEnvironment); + repeater->OnEnvironmentsTearDownEnd(*parent_); + } + + elapsed_time_ = GetTimeInMillis() - start; + + // Tells the unit test event listener that the tests have just finished. + repeater->OnTestIterationEnd(*parent_, i); + + // Gets the result and clears it. + if (!Passed()) { + failed = true; + } + + // Restores the original test order after the iteration. This + // allows the user to quickly repro a failure that happens in the + // N-th iteration without repeating the first (N - 1) iterations. + // This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in + // case the user somehow changes the value of the flag somewhere + // (it's always safe to unshuffle the tests). + UnshuffleTests(); + + if (GTEST_FLAG(shuffle)) { + // Picks a new random seed for each iteration. + random_seed_ = GetNextRandomSeed(random_seed_); + } + } + + repeater->OnTestProgramEnd(*parent_); + + return !failed; +} + +// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file +// if the variable is present. If a file already exists at this location, this +// function will write over it. If the variable is present, but the file cannot +// be created, prints an error and exits. +void WriteToShardStatusFileIfNeeded() { + const char* const test_shard_file = posix::GetEnv(kTestShardStatusFile); + if (test_shard_file != NULL) { + FILE* const file = posix::FOpen(test_shard_file, "w"); + if (file == NULL) { + ColoredPrintf(COLOR_RED, + "Could not write to the test shard status file \"%s\" " + "specified by the %s environment variable.\n", + test_shard_file, kTestShardStatusFile); + fflush(stdout); + exit(EXIT_FAILURE); + } + fclose(file); + } +} + +// Checks whether sharding is enabled by examining the relevant +// environment variable values. If the variables are present, +// but inconsistent (i.e., shard_index >= total_shards), prints +// an error and exits. If in_subprocess_for_death_test, sharding is +// disabled because it must only be applied to the original test +// process. Otherwise, we could filter out death tests we intended to execute. +bool ShouldShard(const char* total_shards_env, + const char* shard_index_env, + bool in_subprocess_for_death_test) { + if (in_subprocess_for_death_test) { + return false; + } + + const Int32 total_shards = Int32FromEnvOrDie(total_shards_env, -1); + const Int32 shard_index = Int32FromEnvOrDie(shard_index_env, -1); + + if (total_shards == -1 && shard_index == -1) { + return false; + } else if (total_shards == -1 && shard_index != -1) { + const Message msg = Message() + << "Invalid environment variables: you have " + << kTestShardIndex << " = " << shard_index + << ", but have left " << kTestTotalShards << " unset.\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } else if (total_shards != -1 && shard_index == -1) { + const Message msg = Message() + << "Invalid environment variables: you have " + << kTestTotalShards << " = " << total_shards + << ", but have left " << kTestShardIndex << " unset.\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } else if (shard_index < 0 || shard_index >= total_shards) { + const Message msg = Message() + << "Invalid environment variables: we require 0 <= " + << kTestShardIndex << " < " << kTestTotalShards + << ", but you have " << kTestShardIndex << "=" << shard_index + << ", " << kTestTotalShards << "=" << total_shards << ".\n"; + ColoredPrintf(COLOR_RED, msg.GetString().c_str()); + fflush(stdout); + exit(EXIT_FAILURE); + } + + return total_shards > 1; +} + +// Parses the environment variable var as an Int32. If it is unset, +// returns default_val. If it is not an Int32, prints an error +// and aborts. +Int32 Int32FromEnvOrDie(const char* var, Int32 default_val) { + const char* str_val = posix::GetEnv(var); + if (str_val == NULL) { + return default_val; + } + + Int32 result; + if (!ParseInt32(Message() << "The value of environment variable " << var, + str_val, &result)) { + exit(EXIT_FAILURE); + } + return result; +} + +// Given the total number of shards, the shard index, and the test id, +// returns true iff the test should be run on this shard. The test id is +// some arbitrary but unique non-negative integer assigned to each test +// method. Assumes that 0 <= shard_index < total_shards. +bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) { + return (test_id % total_shards) == shard_index; +} + +// Compares the name of each test with the user-specified filter to +// decide whether the test should be run, then records the result in +// each TestCase and TestInfo object. +// If shard_tests == true, further filters tests based on sharding +// variables in the environment - see +// http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide. +// Returns the number of tests that should run. +int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) { + const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ? + Int32FromEnvOrDie(kTestTotalShards, -1) : -1; + const Int32 shard_index = shard_tests == HONOR_SHARDING_PROTOCOL ? + Int32FromEnvOrDie(kTestShardIndex, -1) : -1; + + // num_runnable_tests are the number of tests that will + // run across all shards (i.e., match filter and are not disabled). + // num_selected_tests are the number of tests to be run on + // this shard. + int num_runnable_tests = 0; + int num_selected_tests = 0; + for (size_t i = 0; i < test_cases_.size(); i++) { + TestCase* const test_case = test_cases_[i]; + const std::string &test_case_name = test_case->name(); + test_case->set_should_run(false); + + for (size_t j = 0; j < test_case->test_info_list().size(); j++) { + TestInfo* const test_info = test_case->test_info_list()[j]; + const std::string test_name(test_info->name()); + // A test is disabled if test case name or test name matches + // kDisableTestFilter. + const bool is_disabled = + internal::UnitTestOptions::MatchesFilter(test_case_name, + kDisableTestFilter) || + internal::UnitTestOptions::MatchesFilter(test_name, + kDisableTestFilter); + test_info->is_disabled_ = is_disabled; + + const bool matches_filter = + internal::UnitTestOptions::FilterMatchesTest(test_case_name, + test_name); + test_info->matches_filter_ = matches_filter; + + const bool is_runnable = + (GTEST_FLAG(also_run_disabled_tests) || !is_disabled) && + matches_filter; + + const bool is_selected = is_runnable && + (shard_tests == IGNORE_SHARDING_PROTOCOL || + ShouldRunTestOnShard(total_shards, shard_index, + num_runnable_tests)); + + num_runnable_tests += is_runnable; + num_selected_tests += is_selected; + + test_info->should_run_ = is_selected; + test_case->set_should_run(test_case->should_run() || is_selected); + } + } + return num_selected_tests; +} + +// Prints the given C-string on a single line by replacing all '\n' +// characters with string "\\n". If the output takes more than +// max_length characters, only prints the first max_length characters +// and "...". +static void PrintOnOneLine(const char* str, int max_length) { + if (str != NULL) { + for (int i = 0; *str != '\0'; ++str) { + if (i >= max_length) { + printf("..."); + break; + } + if (*str == '\n') { + printf("\\n"); + i += 2; + } else { + printf("%c", *str); + ++i; + } + } + } +} + +// Prints the names of the tests matching the user-specified filter flag. +void UnitTestImpl::ListTestsMatchingFilter() { + // Print at most this many characters for each type/value parameter. + const int kMaxParamLength = 250; + + for (size_t i = 0; i < test_cases_.size(); i++) { + const TestCase* const test_case = test_cases_[i]; + bool printed_test_case_name = false; + + for (size_t j = 0; j < test_case->test_info_list().size(); j++) { + const TestInfo* const test_info = + test_case->test_info_list()[j]; + if (test_info->matches_filter_) { + if (!printed_test_case_name) { + printed_test_case_name = true; + printf("%s.", test_case->name()); + if (test_case->type_param() != NULL) { + printf(" # %s = ", kTypeParamLabel); + // We print the type parameter on a single line to make + // the output easy to parse by a program. + PrintOnOneLine(test_case->type_param(), kMaxParamLength); + } + printf("\n"); + } + printf(" %s", test_info->name()); + if (test_info->value_param() != NULL) { + printf(" # %s = ", kValueParamLabel); + // We print the value parameter on a single line to make the + // output easy to parse by a program. + PrintOnOneLine(test_info->value_param(), kMaxParamLength); + } + printf("\n"); + } + } + } + fflush(stdout); +} + +// Sets the OS stack trace getter. +// +// Does nothing if the input and the current OS stack trace getter are +// the same; otherwise, deletes the old getter and makes the input the +// current getter. +void UnitTestImpl::set_os_stack_trace_getter( + OsStackTraceGetterInterface* getter) { + if (os_stack_trace_getter_ != getter) { + delete os_stack_trace_getter_; + os_stack_trace_getter_ = getter; + } +} + +// Returns the current OS stack trace getter if it is not NULL; +// otherwise, creates an OsStackTraceGetter, makes it the current +// getter, and returns it. +OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() { + if (os_stack_trace_getter_ == NULL) { + os_stack_trace_getter_ = new OsStackTraceGetter; + } + + return os_stack_trace_getter_; +} + +// Returns the TestResult for the test that's currently running, or +// the TestResult for the ad hoc test if no test is running. +TestResult* UnitTestImpl::current_test_result() { + return current_test_info_ ? + &(current_test_info_->result_) : &ad_hoc_test_result_; +} + +// Shuffles all test cases, and the tests within each test case, +// making sure that death tests are still run first. +void UnitTestImpl::ShuffleTests() { + // Shuffles the death test cases. + ShuffleRange(random(), 0, last_death_test_case_ + 1, &test_case_indices_); + + // Shuffles the non-death test cases. + ShuffleRange(random(), last_death_test_case_ + 1, + static_cast(test_cases_.size()), &test_case_indices_); + + // Shuffles the tests inside each test case. + for (size_t i = 0; i < test_cases_.size(); i++) { + test_cases_[i]->ShuffleTests(random()); + } +} + +// Restores the test cases and tests to their order before the first shuffle. +void UnitTestImpl::UnshuffleTests() { + for (size_t i = 0; i < test_cases_.size(); i++) { + // Unshuffles the tests in each test case. + test_cases_[i]->UnshuffleTests(); + // Resets the index of each test case. + test_case_indices_[i] = static_cast(i); + } +} + +// Returns the current OS stack trace as an std::string. +// +// The maximum number of stack frames to be included is specified by +// the gtest_stack_trace_depth flag. The skip_count parameter +// specifies the number of top frames to be skipped, which doesn't +// count against the number of frames to be included. +// +// For example, if Foo() calls Bar(), which in turn calls +// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in +// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't. +std::string GetCurrentOsStackTraceExceptTop(UnitTest* /*unit_test*/, + int skip_count) { + // We pass skip_count + 1 to skip this wrapper function in addition + // to what the user really wants to skip. + return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1); +} + +// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to +// suppress unreachable code warnings. +namespace { +class ClassUniqueToAlwaysTrue {}; +} + +bool IsTrue(bool condition) { return condition; } + +bool AlwaysTrue() { +#if GTEST_HAS_EXCEPTIONS + // This condition is always false so AlwaysTrue() never actually throws, + // but it makes the compiler think that it may throw. + if (IsTrue(false)) + throw ClassUniqueToAlwaysTrue(); +#endif // GTEST_HAS_EXCEPTIONS + return true; +} + +// If *pstr starts with the given prefix, modifies *pstr to be right +// past the prefix and returns true; otherwise leaves *pstr unchanged +// and returns false. None of pstr, *pstr, and prefix can be NULL. +bool SkipPrefix(const char* prefix, const char** pstr) { + const size_t prefix_len = strlen(prefix); + if (strncmp(*pstr, prefix, prefix_len) == 0) { + *pstr += prefix_len; + return true; + } + return false; +} + +// Parses a string as a command line flag. The string should have +// the format "--flag=value". When def_optional is true, the "=value" +// part can be omitted. +// +// Returns the value of the flag, or NULL if the parsing failed. +const char* ParseFlagValue(const char* str, + const char* flag, + bool def_optional) { + // str and flag must not be NULL. + if (str == NULL || flag == NULL) return NULL; + + // The flag must start with "--" followed by GTEST_FLAG_PREFIX_. + const std::string flag_str = std::string("--") + GTEST_FLAG_PREFIX_ + flag; + const size_t flag_len = flag_str.length(); + if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL; + + // Skips the flag name. + const char* flag_end = str + flag_len; + + // When def_optional is true, it's OK to not have a "=value" part. + if (def_optional && (flag_end[0] == '\0')) { + return flag_end; + } + + // If def_optional is true and there are more characters after the + // flag name, or if def_optional is false, there must be a '=' after + // the flag name. + if (flag_end[0] != '=') return NULL; + + // Returns the string after "=". + return flag_end + 1; +} + +// Parses a string for a bool flag, in the form of either +// "--flag=value" or "--flag". +// +// In the former case, the value is taken as true as long as it does +// not start with '0', 'f', or 'F'. +// +// In the latter case, the value is taken as true. +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseBoolFlag(const char* str, const char* flag, bool* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(str, flag, true); + + // Aborts if the parsing failed. + if (value_str == NULL) return false; + + // Converts the string value to a bool. + *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F'); + return true; +} + +// Parses a string for an Int32 flag, in the form of +// "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseInt32Flag(const char* str, const char* flag, Int32* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(str, flag, false); + + // Aborts if the parsing failed. + if (value_str == NULL) return false; + + // Sets *value to the value of the flag. + return ParseInt32(Message() << "The value of flag --" << flag, + value_str, value); +} + +// Parses a string for a string flag, in the form of +// "--flag=value". +// +// On success, stores the value of the flag in *value, and returns +// true. On failure, returns false without changing *value. +bool ParseStringFlag(const char* str, const char* flag, std::string* value) { + // Gets the value of the flag as a string. + const char* const value_str = ParseFlagValue(str, flag, false); + + // Aborts if the parsing failed. + if (value_str == NULL) return false; + + // Sets *value to the value of the flag. + *value = value_str; + return true; +} + +// Determines whether a string has a prefix that Google Test uses for its +// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_. +// If Google Test detects that a command line flag has its prefix but is not +// recognized, it will print its help message. Flags starting with +// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test +// internal flags and do not trigger the help message. +static bool HasGoogleTestFlagPrefix(const char* str) { + return (SkipPrefix("--", &str) || + SkipPrefix("-", &str) || + SkipPrefix("/", &str)) && + !SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) && + (SkipPrefix(GTEST_FLAG_PREFIX_, &str) || + SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str)); +} + +// Prints a string containing code-encoded text. The following escape +// sequences can be used in the string to control the text color: +// +// @@ prints a single '@' character. +// @R changes the color to red. +// @G changes the color to green. +// @Y changes the color to yellow. +// @D changes to the default terminal text color. +// +// TODO(wan@google.com): Write tests for this once we add stdout +// capturing to Google Test. +static void PrintColorEncoded(const char* str) { + GTestColor color = COLOR_DEFAULT; // The current color. + + // Conceptually, we split the string into segments divided by escape + // sequences. Then we print one segment at a time. At the end of + // each iteration, the str pointer advances to the beginning of the + // next segment. + for (;;) { + const char* p = strchr(str, '@'); + if (p == NULL) { + ColoredPrintf(color, "%s", str); + return; + } + + ColoredPrintf(color, "%s", std::string(str, p).c_str()); + + const char ch = p[1]; + str = p + 2; + if (ch == '@') { + ColoredPrintf(color, "@"); + } else if (ch == 'D') { + color = COLOR_DEFAULT; + } else if (ch == 'R') { + color = COLOR_RED; + } else if (ch == 'G') { + color = COLOR_GREEN; + } else if (ch == 'Y') { + color = COLOR_YELLOW; + } else { + --str; + } + } +} + +static const char kColorEncodedHelpMessage[] = +"This program contains tests written using " GTEST_NAME_ ". You can use the\n" +"following command line flags to control its behavior:\n" +"\n" +"Test Selection:\n" +" @G--" GTEST_FLAG_PREFIX_ "list_tests@D\n" +" List the names of all tests instead of running them. The name of\n" +" TEST(Foo, Bar) is \"Foo.Bar\".\n" +" @G--" GTEST_FLAG_PREFIX_ "filter=@YPOSTIVE_PATTERNS" + "[@G-@YNEGATIVE_PATTERNS]@D\n" +" Run only the tests whose name matches one of the positive patterns but\n" +" none of the negative patterns. '?' matches any single character; '*'\n" +" matches any substring; ':' separates two patterns.\n" +" @G--" GTEST_FLAG_PREFIX_ "also_run_disabled_tests@D\n" +" Run all disabled tests too.\n" +"\n" +"Test Execution:\n" +" @G--" GTEST_FLAG_PREFIX_ "repeat=@Y[COUNT]@D\n" +" Run the tests repeatedly; use a negative count to repeat forever.\n" +" @G--" GTEST_FLAG_PREFIX_ "shuffle@D\n" +" Randomize tests' orders on every iteration.\n" +" @G--" GTEST_FLAG_PREFIX_ "random_seed=@Y[NUMBER]@D\n" +" Random number seed to use for shuffling test orders (between 1 and\n" +" 99999, or 0 to use a seed based on the current time).\n" +"\n" +"Test Output:\n" +" @G--" GTEST_FLAG_PREFIX_ "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\n" +" Enable/disable colored output. The default is @Gauto@D.\n" +" -@G-" GTEST_FLAG_PREFIX_ "print_time=0@D\n" +" Don't print the elapsed time of each test.\n" +" @G--" GTEST_FLAG_PREFIX_ "output=xml@Y[@G:@YDIRECTORY_PATH@G" + GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n" +" Generate an XML report in the given directory or with the given file\n" +" name. @YFILE_PATH@D defaults to @Gtest_details.xml@D.\n" +#if GTEST_CAN_STREAM_RESULTS_ +" @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST@G:@YPORT@D\n" +" Stream test results to the given server.\n" +#endif // GTEST_CAN_STREAM_RESULTS_ +"\n" +"Assertion Behavior:\n" +#if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS +" @G--" GTEST_FLAG_PREFIX_ "death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n" +" Set the default death test style.\n" +#endif // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS +" @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n" +" Turn assertion failures into debugger break-points.\n" +" @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n" +" Turn assertion failures into C++ exceptions.\n" +" @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n" +" Do not report exceptions as test failures. Instead, allow them\n" +" to crash the program or throw a pop-up (on Windows).\n" +"\n" +"Except for @G--" GTEST_FLAG_PREFIX_ "list_tests@D, you can alternatively set " + "the corresponding\n" +"environment variable of a flag (all letters in upper-case). For example, to\n" +"disable colored text output, you can either specify @G--" GTEST_FLAG_PREFIX_ + "color=no@D or set\n" +"the @G" GTEST_FLAG_PREFIX_UPPER_ "COLOR@D environment variable to @Gno@D.\n" +"\n" +"For more information, please read the " GTEST_NAME_ " documentation at\n" +"@G" GTEST_PROJECT_URL_ "@D. If you find a bug in " GTEST_NAME_ "\n" +"(not one in your own code or tests), please report it to\n" +"@G<" GTEST_DEV_EMAIL_ ">@D.\n"; + +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. The type parameter CharType can be +// instantiated to either char or wchar_t. +template +void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) { + for (int i = 1; i < *argc; i++) { + const std::string arg_string = StreamableToString(argv[i]); + const char* const arg = arg_string.c_str(); + + using internal::ParseBoolFlag; + using internal::ParseInt32Flag; + using internal::ParseStringFlag; + + // Do we see a Google Test flag? + if (ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag, + >EST_FLAG(also_run_disabled_tests)) || + ParseBoolFlag(arg, kBreakOnFailureFlag, + >EST_FLAG(break_on_failure)) || + ParseBoolFlag(arg, kCatchExceptionsFlag, + >EST_FLAG(catch_exceptions)) || + ParseStringFlag(arg, kColorFlag, >EST_FLAG(color)) || + ParseStringFlag(arg, kDeathTestStyleFlag, + >EST_FLAG(death_test_style)) || + ParseBoolFlag(arg, kDeathTestUseFork, + >EST_FLAG(death_test_use_fork)) || + ParseStringFlag(arg, kFilterFlag, >EST_FLAG(filter)) || + ParseStringFlag(arg, kInternalRunDeathTestFlag, + >EST_FLAG(internal_run_death_test)) || + ParseBoolFlag(arg, kListTestsFlag, >EST_FLAG(list_tests)) || + ParseStringFlag(arg, kOutputFlag, >EST_FLAG(output)) || + ParseBoolFlag(arg, kPrintTimeFlag, >EST_FLAG(print_time)) || + ParseInt32Flag(arg, kRandomSeedFlag, >EST_FLAG(random_seed)) || + ParseInt32Flag(arg, kRepeatFlag, >EST_FLAG(repeat)) || + ParseBoolFlag(arg, kShuffleFlag, >EST_FLAG(shuffle)) || + ParseInt32Flag(arg, kStackTraceDepthFlag, + >EST_FLAG(stack_trace_depth)) || + ParseStringFlag(arg, kStreamResultToFlag, + >EST_FLAG(stream_result_to)) || + ParseBoolFlag(arg, kThrowOnFailureFlag, + >EST_FLAG(throw_on_failure)) + ) { + // Yes. Shift the remainder of the argv list left by one. Note + // that argv has (*argc + 1) elements, the last one always being + // NULL. The following loop moves the trailing NULL element as + // well. + for (int j = i; j != *argc; j++) { + argv[j] = argv[j + 1]; + } + + // Decrements the argument count. + (*argc)--; + + // We also need to decrement the iterator as we just removed + // an element. + i--; + } else if (arg_string == "--help" || arg_string == "-h" || + arg_string == "-?" || arg_string == "/?" || + HasGoogleTestFlagPrefix(arg)) { + // Both help flag and unrecognized Google Test flags (excluding + // internal ones) trigger help display. + g_help_flag = true; + } + } + + if (g_help_flag) { + // We print the help here instead of in RUN_ALL_TESTS(), as the + // latter may not be called at all if the user is using Google + // Test with another testing framework. + PrintColorEncoded(kColorEncodedHelpMessage); + } +} + +// Parses the command line for Google Test flags, without initializing +// other parts of Google Test. +void ParseGoogleTestFlagsOnly(int* argc, char** argv) { + ParseGoogleTestFlagsOnlyImpl(argc, argv); +} +void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv) { + ParseGoogleTestFlagsOnlyImpl(argc, argv); +} + +// The internal implementation of InitGoogleTest(). +// +// The type parameter CharType can be instantiated to either char or +// wchar_t. +template +void InitGoogleTestImpl(int* argc, CharType** argv) { + g_init_gtest_count++; + + // We don't want to run the initialization code twice. + if (g_init_gtest_count != 1) return; + + if (*argc <= 0) return; + + internal::g_executable_path = internal::StreamableToString(argv[0]); + +#if GTEST_HAS_DEATH_TEST + + g_argvs.clear(); + for (int i = 0; i != *argc; i++) { + g_argvs.push_back(StreamableToString(argv[i])); + } + +#endif // GTEST_HAS_DEATH_TEST + + ParseGoogleTestFlagsOnly(argc, argv); + GetUnitTestImpl()->PostFlagParsingInit(); +} + +} // namespace internal + +// Initializes Google Test. This must be called before calling +// RUN_ALL_TESTS(). In particular, it parses a command line for the +// flags that Google Test recognizes. Whenever a Google Test flag is +// seen, it is removed from argv, and *argc is decremented. +// +// No value is returned. Instead, the Google Test flag variables are +// updated. +// +// Calling the function for the second time has no user-visible effect. +void InitGoogleTest(int* argc, char** argv) { + internal::InitGoogleTestImpl(argc, argv); +} + +// This overloaded version can be used in Windows programs compiled in +// UNICODE mode. +void InitGoogleTest(int* argc, wchar_t** argv) { + internal::InitGoogleTestImpl(argc, argv); +} + +} // namespace testing +// 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 +// 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), vladl@google.com (Vlad Losev) +// +// This file implements death tests. + + +#if GTEST_HAS_DEATH_TEST + +# if GTEST_OS_MAC +# include +# endif // GTEST_OS_MAC + +# include +# include +# include + +# if GTEST_OS_LINUX +# include +# endif // GTEST_OS_LINUX + +# include + +# if GTEST_OS_WINDOWS +# include +# else +# include +# include +# endif // GTEST_OS_WINDOWS + +# if GTEST_OS_QNX +# include +# endif // GTEST_OS_QNX + +#endif // GTEST_HAS_DEATH_TEST + + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +#undef GTEST_IMPLEMENTATION_ + +namespace testing { + +// Constants. + +// The default death test style. +static const char kDefaultDeathTestStyle[] = "fast"; + +GTEST_DEFINE_string_( + death_test_style, + internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle), + "Indicates how to run a death test in a forked child process: " + "\"threadsafe\" (child process re-executes the test binary " + "from the beginning, running only the specific death test) or " + "\"fast\" (child process runs the death test immediately " + "after forking)."); + +GTEST_DEFINE_bool_( + death_test_use_fork, + internal::BoolFromGTestEnv("death_test_use_fork", false), + "Instructs to use fork()/_exit() instead of clone() in death tests. " + "Ignored and always uses fork() on POSIX systems where clone() is not " + "implemented. Useful when running under valgrind or similar tools if " + "those do not support clone(). Valgrind 3.3.1 will just fail if " + "it sees an unsupported combination of clone() flags. " + "It is not recommended to use this flag w/o valgrind though it will " + "work in 99% of the cases. Once valgrind is fixed, this flag will " + "most likely be removed."); + +namespace internal { +GTEST_DEFINE_string_( + internal_run_death_test, "", + "Indicates the file, line number, temporal index of " + "the single death test to run, and a file descriptor to " + "which a success code may be sent, all separated by " + "the '|' characters. This flag is specified if and only if the current " + "process is a sub-process launched for running a thread-safe " + "death test. FOR INTERNAL USE ONLY."); +} // namespace internal + +#if GTEST_HAS_DEATH_TEST + +namespace internal { + +// Valid only for fast death tests. Indicates the code is running in the +// child process of a fast style death test. +static bool g_in_fast_death_test_child = false; + +// Returns a Boolean value indicating whether the caller is currently +// executing in the context of the death test child process. Tools such as +// Valgrind heap checkers may need this to modify their behavior in death +// tests. IMPORTANT: This is an internal utility. Using it may break the +// implementation of death tests. User code MUST NOT use it. +bool InDeathTestChild() { +# if GTEST_OS_WINDOWS + + // On Windows, death tests are thread-safe regardless of the value of the + // death_test_style flag. + return !GTEST_FLAG(internal_run_death_test).empty(); + +# else + + if (GTEST_FLAG(death_test_style) == "threadsafe") + return !GTEST_FLAG(internal_run_death_test).empty(); + else + return g_in_fast_death_test_child; +#endif +} + +} // namespace internal + +// ExitedWithCode constructor. +ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) { +} + +// ExitedWithCode function-call operator. +bool ExitedWithCode::operator()(int exit_status) const { +# if GTEST_OS_WINDOWS + + return exit_status == exit_code_; + +# else + + return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_; + +# endif // GTEST_OS_WINDOWS +} + +# if !GTEST_OS_WINDOWS +// KilledBySignal constructor. +KilledBySignal::KilledBySignal(int signum) : signum_(signum) { +} + +// KilledBySignal function-call operator. +bool KilledBySignal::operator()(int exit_status) const { + return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_; +} +# endif // !GTEST_OS_WINDOWS + +namespace internal { + +// Utilities needed for death tests. + +// Generates a textual description of a given exit code, in the format +// specified by wait(2). +static std::string ExitSummary(int exit_code) { + Message m; + +# if GTEST_OS_WINDOWS + + m << "Exited with exit status " << exit_code; + +# else + + if (WIFEXITED(exit_code)) { + m << "Exited with exit status " << WEXITSTATUS(exit_code); + } else if (WIFSIGNALED(exit_code)) { + m << "Terminated by signal " << WTERMSIG(exit_code); + } +# ifdef WCOREDUMP + if (WCOREDUMP(exit_code)) { + m << " (core dumped)"; + } +# endif +# endif // GTEST_OS_WINDOWS + + return m.GetString(); +} + +// Returns true if exit_status describes a process that was terminated +// by a signal, or exited normally with a nonzero exit code. +bool ExitedUnsuccessfully(int exit_status) { + return !ExitedWithCode(0)(exit_status); +} + +# if !GTEST_OS_WINDOWS +// Generates a textual failure message when a death test finds more than +// one thread running, or cannot determine the number of threads, prior +// to executing the given statement. It is the responsibility of the +// caller not to pass a thread_count of 1. +static std::string DeathTestThreadWarning(size_t thread_count) { + Message msg; + msg << "Death tests use fork(), which is unsafe particularly" + << " in a threaded context. For this test, " << GTEST_NAME_ << " "; + if (thread_count == 0) + msg << "couldn't detect the number of threads."; + else + msg << "detected " << thread_count << " threads."; + return msg.GetString(); +} +# endif // !GTEST_OS_WINDOWS + +// Flag characters for reporting a death test that did not die. +static const char kDeathTestLived = 'L'; +static const char kDeathTestReturned = 'R'; +static const char kDeathTestThrew = 'T'; +static const char kDeathTestInternalError = 'I'; + +// An enumeration describing all of the possible ways that a death test can +// conclude. DIED means that the process died while executing the test +// code; LIVED means that process lived beyond the end of the test code; +// RETURNED means that the test statement attempted to execute a return +// statement, which is not allowed; THREW means that the test statement +// returned control by throwing an exception. IN_PROGRESS means the test +// has not yet concluded. +// TODO(vladl@google.com): Unify names and possibly values for +// AbortReason, DeathTestOutcome, and flag characters above. +enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW }; + +// Routine for aborting the program which is safe to call from an +// exec-style death test child process, in which case the error +// message is propagated back to the parent process. Otherwise, the +// message is simply printed to stderr. In either case, the program +// then exits with status 1. +void DeathTestAbort(const std::string& message) { + // On a POSIX system, this function may be called from a threadsafe-style + // death test child process, which operates on a very small stack. Use + // the heap for any additional non-minuscule memory requirements. + const InternalRunDeathTestFlag* const flag = + GetUnitTestImpl()->internal_run_death_test_flag(); + if (flag != NULL) { + FILE* parent = posix::FDOpen(flag->write_fd(), "w"); + fputc(kDeathTestInternalError, parent); + fprintf(parent, "%s", message.c_str()); + fflush(parent); + _exit(1); + } else { + fprintf(stderr, "%s", message.c_str()); + fflush(stderr); + posix::Abort(); + } +} + +// A replacement for CHECK that calls DeathTestAbort if the assertion +// fails. +# define GTEST_DEATH_TEST_CHECK_(expression) \ + do { \ + if (!::testing::internal::IsTrue(expression)) { \ + DeathTestAbort( \ + ::std::string("CHECK failed: File ") + __FILE__ + ", line " \ + + ::testing::internal::StreamableToString(__LINE__) + ": " \ + + #expression); \ + } \ + } while (::testing::internal::AlwaysFalse()) + +// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for +// evaluating any system call that fulfills two conditions: it must return +// -1 on failure, and set errno to EINTR when it is interrupted and +// should be tried again. The macro expands to a loop that repeatedly +// evaluates the expression as long as it evaluates to -1 and sets +// errno to EINTR. If the expression evaluates to -1 but errno is +// something other than EINTR, DeathTestAbort is called. +# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \ + do { \ + int gtest_retval; \ + do { \ + gtest_retval = (expression); \ + } while (gtest_retval == -1 && errno == EINTR); \ + if (gtest_retval == -1) { \ + DeathTestAbort( \ + ::std::string("CHECK failed: File ") + __FILE__ + ", line " \ + + ::testing::internal::StreamableToString(__LINE__) + ": " \ + + #expression + " != -1"); \ + } \ + } while (::testing::internal::AlwaysFalse()) + +// Returns the message describing the last system error in errno. +std::string GetLastErrnoDescription() { + return errno == 0 ? "" : posix::StrError(errno); +} + +// This is called from a death test parent process to read a failure +// message from the death test child process and log it with the FATAL +// severity. On Windows, the message is read from a pipe handle. On other +// platforms, it is read from a file descriptor. +static void FailFromInternalError(int fd) { + Message error; + char buffer[256]; + int num_read; + + do { + while ((num_read = posix::Read(fd, buffer, 255)) > 0) { + buffer[num_read] = '\0'; + error << buffer; + } + } while (num_read == -1 && errno == EINTR); + + if (num_read == 0) { + GTEST_LOG_(FATAL) << error.GetString(); + } else { + const int last_error = errno; + GTEST_LOG_(FATAL) << "Error while reading death test internal: " + << GetLastErrnoDescription() << " [" << last_error << "]"; + } +} + +// Death test constructor. Increments the running death test count +// for the current test. +DeathTest::DeathTest() { + TestInfo* const info = GetUnitTestImpl()->current_test_info(); + if (info == NULL) { + DeathTestAbort("Cannot run a death test outside of a TEST or " + "TEST_F construct"); + } +} + +// Creates and returns a death test by dispatching to the current +// death test factory. +bool DeathTest::Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test) { + return GetUnitTestImpl()->death_test_factory()->Create( + statement, regex, file, line, test); +} + +const char* DeathTest::LastMessage() { + return last_death_test_message_.c_str(); +} + +void DeathTest::set_last_death_test_message(const std::string& message) { + last_death_test_message_ = message; +} + +std::string DeathTest::last_death_test_message_; + +// Provides cross platform implementation for some death functionality. +class DeathTestImpl : public DeathTest { + protected: + DeathTestImpl(const char* a_statement, const RE* a_regex) + : statement_(a_statement), + regex_(a_regex), + spawned_(false), + status_(-1), + outcome_(IN_PROGRESS), + read_fd_(-1), + write_fd_(-1) {} + + // read_fd_ is expected to be closed and cleared by a derived class. + ~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); } + + void Abort(AbortReason reason); + virtual bool Passed(bool status_ok); + + const char* statement() const { return statement_; } + const RE* regex() const { return regex_; } + bool spawned() const { return spawned_; } + void set_spawned(bool is_spawned) { spawned_ = is_spawned; } + int status() const { return status_; } + void set_status(int a_status) { status_ = a_status; } + DeathTestOutcome outcome() const { return outcome_; } + void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; } + int read_fd() const { return read_fd_; } + void set_read_fd(int fd) { read_fd_ = fd; } + int write_fd() const { return write_fd_; } + void set_write_fd(int fd) { write_fd_ = fd; } + + // Called in the parent process only. Reads the result code of the death + // test child process via a pipe, interprets it to set the outcome_ + // member, and closes read_fd_. Outputs diagnostics and terminates in + // case of unexpected codes. + void ReadAndInterpretStatusByte(); + + private: + // The textual content of the code this object is testing. This class + // doesn't own this string and should not attempt to delete it. + const char* const statement_; + // The regular expression which test output must match. DeathTestImpl + // doesn't own this object and should not attempt to delete it. + const RE* const regex_; + // True if the death test child process has been successfully spawned. + bool spawned_; + // The exit status of the child process. + int status_; + // How the death test concluded. + DeathTestOutcome outcome_; + // Descriptor to the read end of the pipe to the child process. It is + // always -1 in the child process. The child keeps its write end of the + // pipe in write_fd_. + int read_fd_; + // Descriptor to the child's write end of the pipe to the parent process. + // It is always -1 in the parent process. The parent keeps its end of the + // pipe in read_fd_. + int write_fd_; +}; + +// Called in the parent process only. Reads the result code of the death +// test child process via a pipe, interprets it to set the outcome_ +// member, and closes read_fd_. Outputs diagnostics and terminates in +// case of unexpected codes. +void DeathTestImpl::ReadAndInterpretStatusByte() { + char flag; + int bytes_read; + + // The read() here blocks until data is available (signifying the + // failure of the death test) or until the pipe is closed (signifying + // its success), so it's okay to call this in the parent before + // the child process has exited. + do { + bytes_read = posix::Read(read_fd(), &flag, 1); + } while (bytes_read == -1 && errno == EINTR); + + if (bytes_read == 0) { + set_outcome(DIED); + } else if (bytes_read == 1) { + switch (flag) { + case kDeathTestReturned: + set_outcome(RETURNED); + break; + case kDeathTestThrew: + set_outcome(THREW); + break; + case kDeathTestLived: + set_outcome(LIVED); + break; + case kDeathTestInternalError: + FailFromInternalError(read_fd()); // Does not return. + break; + default: + GTEST_LOG_(FATAL) << "Death test child process reported " + << "unexpected status byte (" + << static_cast(flag) << ")"; + } + } else { + GTEST_LOG_(FATAL) << "Read from death test child process failed: " + << GetLastErrnoDescription(); + } + GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd())); + set_read_fd(-1); +} + +// Signals that the death test code which should have exited, didn't. +// Should be called only in a death test child process. +// Writes a status byte to the child's status file descriptor, then +// calls _exit(1). +void DeathTestImpl::Abort(AbortReason reason) { + // The parent process considers the death test to be a failure if + // it finds any data in our pipe. So, here we write a single flag byte + // to the pipe, then exit. + const char status_ch = + reason == TEST_DID_NOT_DIE ? kDeathTestLived : + reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned; + + GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1)); + // We are leaking the descriptor here because on some platforms (i.e., + // when built as Windows DLL), destructors of global objects will still + // run after calling _exit(). On such systems, write_fd_ will be + // indirectly closed from the destructor of UnitTestImpl, causing double + // close if it is also closed here. On debug configurations, double close + // may assert. As there are no in-process buffers to flush here, we are + // relying on the OS to close the descriptor after the process terminates + // when the destructors are not run. + _exit(1); // Exits w/o any normal exit hooks (we were supposed to crash) +} + +// Returns an indented copy of stderr output for a death test. +// This makes distinguishing death test output lines from regular log lines +// much easier. +static ::std::string FormatDeathTestOutput(const ::std::string& output) { + ::std::string ret; + for (size_t at = 0; ; ) { + const size_t line_end = output.find('\n', at); + ret += "[ DEATH ] "; + if (line_end == ::std::string::npos) { + ret += output.substr(at); + break; + } + ret += output.substr(at, line_end + 1 - at); + at = line_end + 1; + } + return ret; +} + +// Assesses the success or failure of a death test, using both private +// members which have previously been set, and one argument: +// +// Private data members: +// outcome: An enumeration describing how the death test +// concluded: DIED, LIVED, THREW, or RETURNED. The death test +// fails in the latter three cases. +// status: The exit status of the child process. On *nix, it is in the +// in the format specified by wait(2). On Windows, this is the +// value supplied to the ExitProcess() API or a numeric code +// of the exception that terminated the program. +// regex: A regular expression object to be applied to +// the test's captured standard error output; the death test +// fails if it does not match. +// +// Argument: +// status_ok: true if exit_status is acceptable in the context of +// this particular death test, which fails if it is false +// +// Returns true iff all of the above conditions are met. Otherwise, the +// first failing condition, in the order given above, is the one that is +// reported. Also sets the last death test message string. +bool DeathTestImpl::Passed(bool status_ok) { + if (!spawned()) + return false; + + const std::string error_message = GetCapturedStderr(); + + bool success = false; + Message buffer; + + buffer << "Death test: " << statement() << "\n"; + switch (outcome()) { + case LIVED: + buffer << " Result: failed to die.\n" + << " Error msg:\n" << FormatDeathTestOutput(error_message); + break; + case THREW: + buffer << " Result: threw an exception.\n" + << " Error msg:\n" << FormatDeathTestOutput(error_message); + break; + case RETURNED: + buffer << " Result: illegal return in test statement.\n" + << " Error msg:\n" << FormatDeathTestOutput(error_message); + break; + case DIED: + if (status_ok) { + const bool matched = RE::PartialMatch(error_message.c_str(), *regex()); + if (matched) { + success = true; + } else { + buffer << " Result: died but not with expected error.\n" + << " Expected: " << regex()->pattern() << "\n" + << "Actual msg:\n" << FormatDeathTestOutput(error_message); + } + } else { + buffer << " Result: died but not with expected exit code:\n" + << " " << ExitSummary(status()) << "\n" + << "Actual msg:\n" << FormatDeathTestOutput(error_message); + } + break; + case IN_PROGRESS: + default: + GTEST_LOG_(FATAL) + << "DeathTest::Passed somehow called before conclusion of test"; + } + + DeathTest::set_last_death_test_message(buffer.GetString()); + return success; +} + +# if GTEST_OS_WINDOWS +// WindowsDeathTest implements death tests on Windows. Due to the +// specifics of starting new processes on Windows, death tests there are +// always threadsafe, and Google Test considers the +// --gtest_death_test_style=fast setting to be equivalent to +// --gtest_death_test_style=threadsafe there. +// +// A few implementation notes: Like the Linux version, the Windows +// implementation uses pipes for child-to-parent communication. But due to +// the specifics of pipes on Windows, some extra steps are required: +// +// 1. The parent creates a communication pipe and stores handles to both +// ends of it. +// 2. The parent starts the child and provides it with the information +// necessary to acquire the handle to the write end of the pipe. +// 3. The child acquires the write end of the pipe and signals the parent +// using a Windows event. +// 4. Now the parent can release the write end of the pipe on its side. If +// this is done before step 3, the object's reference count goes down to +// 0 and it is destroyed, preventing the child from acquiring it. The +// parent now has to release it, or read operations on the read end of +// the pipe will not return when the child terminates. +// 5. The parent reads child's output through the pipe (outcome code and +// any possible error messages) from the pipe, and its stderr and then +// determines whether to fail the test. +// +// Note: to distinguish Win32 API calls from the local method and function +// calls, the former are explicitly resolved in the global namespace. +// +class WindowsDeathTest : public DeathTestImpl { + public: + WindowsDeathTest(const char* a_statement, + const RE* a_regex, + const char* file, + int line) + : DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {} + + // All of these virtual functions are inherited from DeathTest. + virtual int Wait(); + virtual TestRole AssumeRole(); + + private: + // The name of the file in which the death test is located. + const char* const file_; + // The line number on which the death test is located. + const int line_; + // Handle to the write end of the pipe to the child process. + AutoHandle write_handle_; + // Child process handle. + AutoHandle child_handle_; + // Event the child process uses to signal the parent that it has + // acquired the handle to the write end of the pipe. After seeing this + // event the parent can release its own handles to make sure its + // ReadFile() calls return when the child terminates. + AutoHandle event_handle_; +}; + +// Waits for the child in a death test to exit, returning its exit +// status, or 0 if no child process exists. As a side effect, sets the +// outcome data member. +int WindowsDeathTest::Wait() { + if (!spawned()) + return 0; + + // Wait until the child either signals that it has acquired the write end + // of the pipe or it dies. + const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() }; + switch (::WaitForMultipleObjects(2, + wait_handles, + FALSE, // Waits for any of the handles. + INFINITE)) { + case WAIT_OBJECT_0: + case WAIT_OBJECT_0 + 1: + break; + default: + GTEST_DEATH_TEST_CHECK_(false); // Should not get here. + } + + // The child has acquired the write end of the pipe or exited. + // We release the handle on our side and continue. + write_handle_.Reset(); + event_handle_.Reset(); + + ReadAndInterpretStatusByte(); + + // Waits for the child process to exit if it haven't already. This + // returns immediately if the child has already exited, regardless of + // whether previous calls to WaitForMultipleObjects synchronized on this + // handle or not. + GTEST_DEATH_TEST_CHECK_( + WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(), + INFINITE)); + DWORD status_code; + GTEST_DEATH_TEST_CHECK_( + ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE); + child_handle_.Reset(); + set_status(static_cast(status_code)); + return status(); +} + +// The AssumeRole process for a Windows death test. It creates a child +// process with the same executable as the current process to run the +// death test. The child process is given the --gtest_filter and +// --gtest_internal_run_death_test flags such that it knows to run the +// current death test only. +DeathTest::TestRole WindowsDeathTest::AssumeRole() { + const UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const TestInfo* const info = impl->current_test_info(); + const int death_test_index = info->result()->death_test_count(); + + if (flag != NULL) { + // ParseInternalRunDeathTestFlag() has performed all the necessary + // processing. + set_write_fd(flag->write_fd()); + return EXECUTE_TEST; + } + + // WindowsDeathTest uses an anonymous pipe to communicate results of + // a death test. + SECURITY_ATTRIBUTES handles_are_inheritable = { + sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; + HANDLE read_handle, write_handle; + GTEST_DEATH_TEST_CHECK_( + ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable, + 0) // Default buffer size. + != FALSE); + set_read_fd(::_open_osfhandle(reinterpret_cast(read_handle), + O_RDONLY)); + write_handle_.Reset(write_handle); + event_handle_.Reset(::CreateEvent( + &handles_are_inheritable, + TRUE, // The event will automatically reset to non-signaled state. + FALSE, // The initial state is non-signalled. + NULL)); // The even is unnamed. + GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL); + const std::string filter_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" + + info->test_case_name() + "." + info->name(); + const std::string internal_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + + "=" + file_ + "|" + StreamableToString(line_) + "|" + + StreamableToString(death_test_index) + "|" + + StreamableToString(static_cast(::GetCurrentProcessId())) + + // size_t has the same width as pointers on both 32-bit and 64-bit + // Windows platforms. + // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx. + "|" + StreamableToString(reinterpret_cast(write_handle)) + + "|" + StreamableToString(reinterpret_cast(event_handle_.Get())); + + char executable_path[_MAX_PATH + 1]; // NOLINT + GTEST_DEATH_TEST_CHECK_( + _MAX_PATH + 1 != ::GetModuleFileNameA(NULL, + executable_path, + _MAX_PATH)); + + std::string command_line = + std::string(::GetCommandLineA()) + " " + filter_flag + " \"" + + internal_flag + "\""; + + DeathTest::set_last_death_test_message(""); + + CaptureStderr(); + // Flush the log buffers since the log streams are shared with the child. + FlushInfoLog(); + + // The child process will share the standard handles with the parent. + STARTUPINFOA startup_info; + memset(&startup_info, 0, sizeof(STARTUPINFO)); + startup_info.dwFlags = STARTF_USESTDHANDLES; + startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE); + startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE); + startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE); + + PROCESS_INFORMATION process_info; + GTEST_DEATH_TEST_CHECK_(::CreateProcessA( + executable_path, + const_cast(command_line.c_str()), + NULL, // Retuned process handle is not inheritable. + NULL, // Retuned thread handle is not inheritable. + TRUE, // Child inherits all inheritable handles (for write_handle_). + 0x0, // Default creation flags. + NULL, // Inherit the parent's environment. + UnitTest::GetInstance()->original_working_dir(), + &startup_info, + &process_info) != FALSE); + child_handle_.Reset(process_info.hProcess); + ::CloseHandle(process_info.hThread); + set_spawned(true); + return OVERSEE_TEST; +} +# else // We are not on Windows. + +// ForkingDeathTest provides implementations for most of the abstract +// methods of the DeathTest interface. Only the AssumeRole method is +// left undefined. +class ForkingDeathTest : public DeathTestImpl { + public: + ForkingDeathTest(const char* statement, const RE* regex); + + // All of these virtual functions are inherited from DeathTest. + virtual int Wait(); + + protected: + void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; } + + private: + // PID of child process during death test; 0 in the child process itself. + pid_t child_pid_; +}; + +// Constructs a ForkingDeathTest. +ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex) + : DeathTestImpl(a_statement, a_regex), + child_pid_(-1) {} + +// Waits for the child in a death test to exit, returning its exit +// status, or 0 if no child process exists. As a side effect, sets the +// outcome data member. +int ForkingDeathTest::Wait() { + if (!spawned()) + return 0; + + ReadAndInterpretStatusByte(); + + int status_value; + GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0)); + set_status(status_value); + return status_value; +} + +// A concrete death test class that forks, then immediately runs the test +// in the child process. +class NoExecDeathTest : public ForkingDeathTest { + public: + NoExecDeathTest(const char* a_statement, const RE* a_regex) : + ForkingDeathTest(a_statement, a_regex) { } + virtual TestRole AssumeRole(); +}; + +// The AssumeRole process for a fork-and-run death test. It implements a +// straightforward fork, with a simple pipe to transmit the status byte. +DeathTest::TestRole NoExecDeathTest::AssumeRole() { + const size_t thread_count = GetThreadCount(); + if (thread_count != 1) { + GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count); + } + + int pipe_fd[2]; + GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1); + + DeathTest::set_last_death_test_message(""); + CaptureStderr(); + // When we fork the process below, the log file buffers are copied, but the + // file descriptors are shared. We flush all log files here so that closing + // the file descriptors in the child process doesn't throw off the + // synchronization between descriptors and buffers in the parent process. + // This is as close to the fork as possible to avoid a race condition in case + // there are multiple threads running before the death test, and another + // thread writes to the log file. + FlushInfoLog(); + + const pid_t child_pid = fork(); + GTEST_DEATH_TEST_CHECK_(child_pid != -1); + set_child_pid(child_pid); + if (child_pid == 0) { + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[0])); + set_write_fd(pipe_fd[1]); + // Redirects all logging to stderr in the child process to prevent + // concurrent writes to the log files. We capture stderr in the parent + // process and append the child process' output to a log. + LogToStderr(); + // Event forwarding to the listeners of event listener API mush be shut + // down in death test subprocesses. + GetUnitTestImpl()->listeners()->SuppressEventForwarding(); + g_in_fast_death_test_child = true; + return EXECUTE_TEST; + } else { + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); + set_read_fd(pipe_fd[0]); + set_spawned(true); + return OVERSEE_TEST; + } +} + +// A concrete death test class that forks and re-executes the main +// program from the beginning, with command-line flags set that cause +// only this specific death test to be run. +class ExecDeathTest : public ForkingDeathTest { + public: + ExecDeathTest(const char* a_statement, const RE* a_regex, + const char* file, int line) : + ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { } + virtual TestRole AssumeRole(); + private: + static ::std::vector + GetArgvsForDeathTestChildProcess() { + ::std::vector args = GetInjectableArgvs(); + return args; + } + // The name of the file in which the death test is located. + const char* const file_; + // The line number on which the death test is located. + const int line_; +}; + +// Utility class for accumulating command-line arguments. +class Arguments { + public: + Arguments() { + args_.push_back(NULL); + } + + ~Arguments() { + for (std::vector::iterator i = args_.begin(); i != args_.end(); + ++i) { + free(*i); + } + } + void AddArgument(const char* argument) { + args_.insert(args_.end() - 1, posix::StrDup(argument)); + } + + template + void AddArguments(const ::std::vector& arguments) { + for (typename ::std::vector::const_iterator i = arguments.begin(); + i != arguments.end(); + ++i) { + args_.insert(args_.end() - 1, posix::StrDup(i->c_str())); + } + } + char* const* Argv() { + return &args_[0]; + } + + private: + std::vector args_; +}; + +// A struct that encompasses the arguments to the child process of a +// threadsafe-style death test process. +struct ExecDeathTestArgs { + char* const* argv; // Command-line arguments for the child's call to exec + int close_fd; // File descriptor to close; the read end of a pipe +}; + +# if GTEST_OS_MAC +inline char** GetEnviron() { + // When Google Test is built as a framework on MacOS X, the environ variable + // is unavailable. Apple's documentation (man environ) recommends using + // _NSGetEnviron() instead. + return *_NSGetEnviron(); +} +# else +// Some POSIX platforms expect you to declare environ. extern "C" makes +// it reside in the global namespace. +extern "C" char** environ; +inline char** GetEnviron() { return environ; } +# endif // GTEST_OS_MAC + +# if !GTEST_OS_QNX +// The main function for a threadsafe-style death test child process. +// This function is called in a clone()-ed process and thus must avoid +// any potentially unsafe operations like malloc or libc functions. +static int ExecDeathTestChildMain(void* child_arg) { + ExecDeathTestArgs* const args = static_cast(child_arg); + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd)); + + // We need to execute the test program in the same environment where + // it was originally invoked. Therefore we change to the original + // working directory first. + const char* const original_dir = + UnitTest::GetInstance()->original_working_dir(); + // We can safely call chdir() as it's a direct system call. + if (chdir(original_dir) != 0) { + DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " + + GetLastErrnoDescription()); + return EXIT_FAILURE; + } + + // We can safely call execve() as it's a direct system call. We + // cannot use execvp() as it's a libc function and thus potentially + // unsafe. Since execve() doesn't search the PATH, the user must + // invoke the test program via a valid path that contains at least + // one path separator. + execve(args->argv[0], args->argv, GetEnviron()); + DeathTestAbort(std::string("execve(") + args->argv[0] + ", ...) in " + + original_dir + " failed: " + + GetLastErrnoDescription()); + return EXIT_FAILURE; +} +# endif // !GTEST_OS_QNX + +// Two utility routines that together determine the direction the stack +// grows. +// This could be accomplished more elegantly by a single recursive +// function, but we want to guard against the unlikely possibility of +// a smart compiler optimizing the recursion away. +// +// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining +// StackLowerThanAddress into StackGrowsDown, which then doesn't give +// correct answer. +void StackLowerThanAddress(const void* ptr, bool* result) GTEST_NO_INLINE_; +void StackLowerThanAddress(const void* ptr, bool* result) { + int dummy; + *result = (&dummy < ptr); +} + +bool StackGrowsDown() { + int dummy; + bool result; + StackLowerThanAddress(&dummy, &result); + return result; +} + +// Spawns a child process with the same executable as the current process in +// a thread-safe manner and instructs it to run the death test. The +// implementation uses fork(2) + exec. On systems where clone(2) is +// available, it is used instead, being slightly more thread-safe. On QNX, +// fork supports only single-threaded environments, so this function uses +// spawn(2) there instead. The function dies with an error message if +// anything goes wrong. +static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) { + ExecDeathTestArgs args = { argv, close_fd }; + pid_t child_pid = -1; + +# if GTEST_OS_QNX + // Obtains the current directory and sets it to be closed in the child + // process. + const int cwd_fd = open(".", O_RDONLY); + GTEST_DEATH_TEST_CHECK_(cwd_fd != -1); + GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC)); + // We need to execute the test program in the same environment where + // it was originally invoked. Therefore we change to the original + // working directory first. + const char* const original_dir = + UnitTest::GetInstance()->original_working_dir(); + // We can safely call chdir() as it's a direct system call. + if (chdir(original_dir) != 0) { + DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " + + GetLastErrnoDescription()); + return EXIT_FAILURE; + } + + int fd_flags; + // Set close_fd to be closed after spawn. + GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD)); + GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(close_fd, F_SETFD, + fd_flags | FD_CLOEXEC)); + struct inheritance inherit = {0}; + // spawn is a system call. + child_pid = spawn(args.argv[0], 0, NULL, &inherit, args.argv, GetEnviron()); + // Restores the current working directory. + GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1); + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd)); + +# else // GTEST_OS_QNX +# if GTEST_OS_LINUX + // When a SIGPROF signal is received while fork() or clone() are executing, + // the process may hang. To avoid this, we ignore SIGPROF here and re-enable + // it after the call to fork()/clone() is complete. + struct sigaction saved_sigprof_action; + struct sigaction ignore_sigprof_action; + memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action)); + sigemptyset(&ignore_sigprof_action.sa_mask); + ignore_sigprof_action.sa_handler = SIG_IGN; + GTEST_DEATH_TEST_CHECK_SYSCALL_(sigaction( + SIGPROF, &ignore_sigprof_action, &saved_sigprof_action)); +# endif // GTEST_OS_LINUX + +# if GTEST_HAS_CLONE + const bool use_fork = GTEST_FLAG(death_test_use_fork); + + if (!use_fork) { + static const bool stack_grows_down = StackGrowsDown(); + const size_t stack_size = getpagesize(); + // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead. + void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, -1, 0); + GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED); + + // Maximum stack alignment in bytes: For a downward-growing stack, this + // amount is subtracted from size of the stack space to get an address + // that is within the stack space and is aligned on all systems we care + // about. As far as I know there is no ABI with stack alignment greater + // than 64. We assume stack and stack_size already have alignment of + // kMaxStackAlignment. + const size_t kMaxStackAlignment = 64; + void* const stack_top = + static_cast(stack) + + (stack_grows_down ? stack_size - kMaxStackAlignment : 0); + GTEST_DEATH_TEST_CHECK_(stack_size > kMaxStackAlignment && + reinterpret_cast(stack_top) % kMaxStackAlignment == 0); + + child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args); + + GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1); + } +# else + const bool use_fork = true; +# endif // GTEST_HAS_CLONE + + if (use_fork && (child_pid = fork()) == 0) { + ExecDeathTestChildMain(&args); + _exit(0); + } +# endif // GTEST_OS_QNX +# if GTEST_OS_LINUX + GTEST_DEATH_TEST_CHECK_SYSCALL_( + sigaction(SIGPROF, &saved_sigprof_action, NULL)); +# endif // GTEST_OS_LINUX + + GTEST_DEATH_TEST_CHECK_(child_pid != -1); + return child_pid; +} + +// The AssumeRole process for a fork-and-exec death test. It re-executes the +// main program from the beginning, setting the --gtest_filter +// and --gtest_internal_run_death_test flags to cause only the current +// death test to be re-run. +DeathTest::TestRole ExecDeathTest::AssumeRole() { + const UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const TestInfo* const info = impl->current_test_info(); + const int death_test_index = info->result()->death_test_count(); + + if (flag != NULL) { + set_write_fd(flag->write_fd()); + return EXECUTE_TEST; + } + + int pipe_fd[2]; + GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1); + // Clear the close-on-exec flag on the write end of the pipe, lest + // it be closed when the child process does an exec: + GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1); + + const std::string filter_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" + + info->test_case_name() + "." + info->name(); + const std::string internal_flag = + std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "=" + + file_ + "|" + StreamableToString(line_) + "|" + + StreamableToString(death_test_index) + "|" + + StreamableToString(pipe_fd[1]); + Arguments args; + args.AddArguments(GetArgvsForDeathTestChildProcess()); + args.AddArgument(filter_flag.c_str()); + args.AddArgument(internal_flag.c_str()); + + DeathTest::set_last_death_test_message(""); + + CaptureStderr(); + // See the comment in NoExecDeathTest::AssumeRole for why the next line + // is necessary. + FlushInfoLog(); + + const pid_t child_pid = ExecDeathTestSpawnChild(args.Argv(), pipe_fd[0]); + GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); + set_child_pid(child_pid); + set_read_fd(pipe_fd[0]); + set_spawned(true); + return OVERSEE_TEST; +} + +# endif // !GTEST_OS_WINDOWS + +// Creates a concrete DeathTest-derived class that depends on the +// --gtest_death_test_style flag, and sets the pointer pointed to +// by the "test" argument to its address. If the test should be +// skipped, sets that pointer to NULL. Returns true, unless the +// flag is set to an invalid value. +bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, + const char* file, int line, + DeathTest** test) { + UnitTestImpl* const impl = GetUnitTestImpl(); + const InternalRunDeathTestFlag* const flag = + impl->internal_run_death_test_flag(); + const int death_test_index = impl->current_test_info() + ->increment_death_test_count(); + + if (flag != NULL) { + if (death_test_index > flag->index()) { + DeathTest::set_last_death_test_message( + "Death test count (" + StreamableToString(death_test_index) + + ") somehow exceeded expected maximum (" + + StreamableToString(flag->index()) + ")"); + return false; + } + + if (!(flag->file() == file && flag->line() == line && + flag->index() == death_test_index)) { + *test = NULL; + return true; + } + } + +# if GTEST_OS_WINDOWS + + if (GTEST_FLAG(death_test_style) == "threadsafe" || + GTEST_FLAG(death_test_style) == "fast") { + *test = new WindowsDeathTest(statement, regex, file, line); + } + +# else + + if (GTEST_FLAG(death_test_style) == "threadsafe") { + *test = new ExecDeathTest(statement, regex, file, line); + } else if (GTEST_FLAG(death_test_style) == "fast") { + *test = new NoExecDeathTest(statement, regex); + } + +# endif // GTEST_OS_WINDOWS + + else { // NOLINT - this is more readable than unbalanced brackets inside #if. + DeathTest::set_last_death_test_message( + "Unknown death test style \"" + GTEST_FLAG(death_test_style) + + "\" encountered"); + return false; + } + + return true; +} + +// Splits a given string on a given delimiter, populating a given +// vector with the fields. GTEST_HAS_DEATH_TEST implies that we have +// ::std::string, so we can use it here. +static void SplitString(const ::std::string& str, char delimiter, + ::std::vector< ::std::string>* dest) { + ::std::vector< ::std::string> parsed; + ::std::string::size_type pos = 0; + while (::testing::internal::AlwaysTrue()) { + const ::std::string::size_type colon = str.find(delimiter, pos); + if (colon == ::std::string::npos) { + parsed.push_back(str.substr(pos)); + break; + } else { + parsed.push_back(str.substr(pos, colon - pos)); + pos = colon + 1; + } + } + dest->swap(parsed); +} + +# if GTEST_OS_WINDOWS +// Recreates the pipe and event handles from the provided parameters, +// signals the event, and returns a file descriptor wrapped around the pipe +// handle. This function is called in the child process only. +int GetStatusFileDescriptor(unsigned int parent_process_id, + size_t write_handle_as_size_t, + size_t event_handle_as_size_t) { + AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE, + FALSE, // Non-inheritable. + parent_process_id)); + if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) { + DeathTestAbort("Unable to open parent process " + + StreamableToString(parent_process_id)); + } + + // TODO(vladl@google.com): Replace the following check with a + // compile-time assertion when available. + GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t)); + + const HANDLE write_handle = + reinterpret_cast(write_handle_as_size_t); + HANDLE dup_write_handle; + + // The newly initialized handle is accessible only in in the parent + // process. To obtain one accessible within the child, we need to use + // DuplicateHandle. + if (!::DuplicateHandle(parent_process_handle.Get(), write_handle, + ::GetCurrentProcess(), &dup_write_handle, + 0x0, // Requested privileges ignored since + // DUPLICATE_SAME_ACCESS is used. + FALSE, // Request non-inheritable handler. + DUPLICATE_SAME_ACCESS)) { + DeathTestAbort("Unable to duplicate the pipe handle " + + StreamableToString(write_handle_as_size_t) + + " from the parent process " + + StreamableToString(parent_process_id)); + } + + const HANDLE event_handle = reinterpret_cast(event_handle_as_size_t); + HANDLE dup_event_handle; + + if (!::DuplicateHandle(parent_process_handle.Get(), event_handle, + ::GetCurrentProcess(), &dup_event_handle, + 0x0, + FALSE, + DUPLICATE_SAME_ACCESS)) { + DeathTestAbort("Unable to duplicate the event handle " + + StreamableToString(event_handle_as_size_t) + + " from the parent process " + + StreamableToString(parent_process_id)); + } + + const int write_fd = + ::_open_osfhandle(reinterpret_cast(dup_write_handle), O_APPEND); + if (write_fd == -1) { + DeathTestAbort("Unable to convert pipe handle " + + StreamableToString(write_handle_as_size_t) + + " to a file descriptor"); + } + + // Signals the parent that the write end of the pipe has been acquired + // so the parent can release its own write end. + ::SetEvent(dup_event_handle); + + return write_fd; +} +# endif // GTEST_OS_WINDOWS + +// Returns a newly created InternalRunDeathTestFlag object with fields +// initialized from the GTEST_FLAG(internal_run_death_test) flag if +// the flag is specified; otherwise returns NULL. +InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() { + if (GTEST_FLAG(internal_run_death_test) == "") return NULL; + + // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we + // can use it here. + int line = -1; + int index = -1; + ::std::vector< ::std::string> fields; + SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields); + int write_fd = -1; + +# if GTEST_OS_WINDOWS + + unsigned int parent_process_id = 0; + size_t write_handle_as_size_t = 0; + size_t event_handle_as_size_t = 0; + + if (fields.size() != 6 + || !ParseNaturalNumber(fields[1], &line) + || !ParseNaturalNumber(fields[2], &index) + || !ParseNaturalNumber(fields[3], &parent_process_id) + || !ParseNaturalNumber(fields[4], &write_handle_as_size_t) + || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) { + DeathTestAbort("Bad --gtest_internal_run_death_test flag: " + + GTEST_FLAG(internal_run_death_test)); + } + write_fd = GetStatusFileDescriptor(parent_process_id, + write_handle_as_size_t, + event_handle_as_size_t); +# else + + if (fields.size() != 4 + || !ParseNaturalNumber(fields[1], &line) + || !ParseNaturalNumber(fields[2], &index) + || !ParseNaturalNumber(fields[3], &write_fd)) { + DeathTestAbort("Bad --gtest_internal_run_death_test flag: " + + GTEST_FLAG(internal_run_death_test)); + } + +# endif // GTEST_OS_WINDOWS + + return new InternalRunDeathTestFlag(fields[0], line, index, write_fd); +} + +} // namespace internal + +#endif // GTEST_HAS_DEATH_TEST + +} // namespace testing +// Copyright 2008, 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. +// +// Authors: keith.ray@gmail.com (Keith Ray) + + +#include + +#if GTEST_OS_WINDOWS_MOBILE +# include +#elif GTEST_OS_WINDOWS +# include +# include +#elif GTEST_OS_SYMBIAN +// Symbian OpenC has PATH_MAX in sys/syslimits.h +# include +#else +# include +# include // Some Linux distributions define PATH_MAX here. +#endif // GTEST_OS_WINDOWS_MOBILE + +#if GTEST_OS_WINDOWS +# define GTEST_PATH_MAX_ _MAX_PATH +#elif defined(PATH_MAX) +# define GTEST_PATH_MAX_ PATH_MAX +#elif defined(_XOPEN_PATH_MAX) +# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX +#else +# define GTEST_PATH_MAX_ _POSIX_PATH_MAX +#endif // GTEST_OS_WINDOWS + + +namespace testing { +namespace internal { + +#if GTEST_OS_WINDOWS +// On Windows, '\\' is the standard path separator, but many tools and the +// Windows API also accept '/' as an alternate path separator. Unless otherwise +// noted, a file path can contain either kind of path separators, or a mixture +// of them. +const char kPathSeparator = '\\'; +const char kAlternatePathSeparator = '/'; +const char kPathSeparatorString[] = "\\"; +const char kAlternatePathSeparatorString[] = "/"; +# if GTEST_OS_WINDOWS_MOBILE +// Windows CE doesn't have a current directory. You should not use +// the current directory in tests on Windows CE, but this at least +// provides a reasonable fallback. +const char kCurrentDirectoryString[] = "\\"; +// Windows CE doesn't define INVALID_FILE_ATTRIBUTES +const DWORD kInvalidFileAttributes = 0xffffffff; +# else +const char kCurrentDirectoryString[] = ".\\"; +# endif // GTEST_OS_WINDOWS_MOBILE +#else +const char kPathSeparator = '/'; +const char kPathSeparatorString[] = "/"; +const char kCurrentDirectoryString[] = "./"; +#endif // GTEST_OS_WINDOWS + +// Returns whether the given character is a valid path separator. +static bool IsPathSeparator(char c) { +#if GTEST_HAS_ALT_PATH_SEP_ + return (c == kPathSeparator) || (c == kAlternatePathSeparator); +#else + return c == kPathSeparator; +#endif +} + +// Returns the current working directory, or "" if unsuccessful. +FilePath FilePath::GetCurrentDir() { +#if GTEST_OS_WINDOWS_MOBILE + // Windows CE doesn't have a current directory, so we just return + // something reasonable. + return FilePath(kCurrentDirectoryString); +#elif GTEST_OS_WINDOWS + char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; + return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); +#else + char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; + return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); +#endif // GTEST_OS_WINDOWS_MOBILE +} + +// Returns a copy of the FilePath with the case-insensitive extension removed. +// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns +// FilePath("dir/file"). If a case-insensitive extension is not +// found, returns a copy of the original FilePath. +FilePath FilePath::RemoveExtension(const char* extension) const { + const std::string dot_extension = std::string(".") + extension; + if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) { + return FilePath(pathname_.substr( + 0, pathname_.length() - dot_extension.length())); + } + return *this; +} + +// Returns a pointer to the last occurence of a valid path separator in +// the FilePath. On Windows, for example, both '/' and '\' are valid path +// separators. Returns NULL if no path separator was found. +const char* FilePath::FindLastPathSeparator() const { + const char* const last_sep = strrchr(c_str(), kPathSeparator); +#if GTEST_HAS_ALT_PATH_SEP_ + const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator); + // Comparing two pointers of which only one is NULL is undefined. + if (last_alt_sep != NULL && + (last_sep == NULL || last_alt_sep > last_sep)) { + return last_alt_sep; + } +#endif + return last_sep; +} + +// Returns a copy of the FilePath with the directory part removed. +// Example: FilePath("path/to/file").RemoveDirectoryName() returns +// FilePath("file"). If there is no directory part ("just_a_file"), it returns +// the FilePath unmodified. If there is no file part ("just_a_dir/") it +// returns an empty FilePath (""). +// On Windows platform, '\' is the path separator, otherwise it is '/'. +FilePath FilePath::RemoveDirectoryName() const { + const char* const last_sep = FindLastPathSeparator(); + return last_sep ? FilePath(last_sep + 1) : *this; +} + +// RemoveFileName returns the directory path with the filename removed. +// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". +// If the FilePath is "a_file" or "/a_file", RemoveFileName returns +// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does +// not have a file, like "just/a/dir/", it returns the FilePath unmodified. +// On Windows platform, '\' is the path separator, otherwise it is '/'. +FilePath FilePath::RemoveFileName() const { + const char* const last_sep = FindLastPathSeparator(); + std::string dir; + if (last_sep) { + dir = std::string(c_str(), last_sep + 1 - c_str()); + } else { + dir = kCurrentDirectoryString; + } + return FilePath(dir); +} + +// Helper functions for naming files in a directory for xml output. + +// Given directory = "dir", base_name = "test", number = 0, +// extension = "xml", returns "dir/test.xml". If number is greater +// than zero (e.g., 12), returns "dir/test_12.xml". +// On Windows platform, uses \ as the separator rather than /. +FilePath FilePath::MakeFileName(const FilePath& directory, + const FilePath& base_name, + int number, + const char* extension) { + std::string file; + if (number == 0) { + file = base_name.string() + "." + extension; + } else { + file = base_name.string() + "_" + StreamableToString(number) + + "." + extension; + } + return ConcatPaths(directory, FilePath(file)); +} + +// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml". +// On Windows, uses \ as the separator rather than /. +FilePath FilePath::ConcatPaths(const FilePath& directory, + const FilePath& relative_path) { + if (directory.IsEmpty()) + return relative_path; + const FilePath dir(directory.RemoveTrailingPathSeparator()); + return FilePath(dir.string() + kPathSeparator + relative_path.string()); +} + +// Returns true if pathname describes something findable in the file-system, +// either a file, directory, or whatever. +bool FilePath::FileOrDirectoryExists() const { +#if GTEST_OS_WINDOWS_MOBILE + LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str()); + const DWORD attributes = GetFileAttributes(unicode); + delete [] unicode; + return attributes != kInvalidFileAttributes; +#else + posix::StatStruct file_stat; + return posix::Stat(pathname_.c_str(), &file_stat) == 0; +#endif // GTEST_OS_WINDOWS_MOBILE +} + +// Returns true if pathname describes a directory in the file-system +// that exists. +bool FilePath::DirectoryExists() const { + bool result = false; +#if GTEST_OS_WINDOWS + // Don't strip off trailing separator if path is a root directory on + // Windows (like "C:\\"). + const FilePath& path(IsRootDirectory() ? *this : + RemoveTrailingPathSeparator()); +#else + const FilePath& path(*this); +#endif + +#if GTEST_OS_WINDOWS_MOBILE + LPCWSTR unicode = String::AnsiToUtf16(path.c_str()); + const DWORD attributes = GetFileAttributes(unicode); + delete [] unicode; + if ((attributes != kInvalidFileAttributes) && + (attributes & FILE_ATTRIBUTE_DIRECTORY)) { + result = true; + } +#else + posix::StatStruct file_stat; + result = posix::Stat(path.c_str(), &file_stat) == 0 && + posix::IsDir(file_stat); +#endif // GTEST_OS_WINDOWS_MOBILE + + return result; +} + +// Returns true if pathname describes a root directory. (Windows has one +// root directory per disk drive.) +bool FilePath::IsRootDirectory() const { +#if GTEST_OS_WINDOWS + // TODO(wan@google.com): on Windows a network share like + // \\server\share can be a root directory, although it cannot be the + // current directory. Handle this properly. + return pathname_.length() == 3 && IsAbsolutePath(); +#else + return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]); +#endif +} + +// Returns true if pathname describes an absolute path. +bool FilePath::IsAbsolutePath() const { + const char* const name = pathname_.c_str(); +#if GTEST_OS_WINDOWS + return pathname_.length() >= 3 && + ((name[0] >= 'a' && name[0] <= 'z') || + (name[0] >= 'A' && name[0] <= 'Z')) && + name[1] == ':' && + IsPathSeparator(name[2]); +#else + return IsPathSeparator(name[0]); +#endif +} + +// Returns a pathname for a file that does not currently exist. The pathname +// will be directory/base_name.extension or +// directory/base_name_.extension if directory/base_name.extension +// already exists. The number will be incremented until a pathname is found +// that does not already exist. +// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. +// There could be a race condition if two or more processes are calling this +// function at the same time -- they could both pick the same filename. +FilePath FilePath::GenerateUniqueFileName(const FilePath& directory, + const FilePath& base_name, + const char* extension) { + FilePath full_pathname; + int number = 0; + do { + full_pathname.Set(MakeFileName(directory, base_name, number++, extension)); + } while (full_pathname.FileOrDirectoryExists()); + return full_pathname; +} + +// Returns true if FilePath ends with a path separator, which indicates that +// it is intended to represent a directory. Returns false otherwise. +// This does NOT check that a directory (or file) actually exists. +bool FilePath::IsDirectory() const { + return !pathname_.empty() && + IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]); +} + +// Create directories so that path exists. Returns true if successful or if +// the directories already exist; returns false if unable to create directories +// for any reason. +bool FilePath::CreateDirectoriesRecursively() const { + if (!this->IsDirectory()) { + return false; + } + + if (pathname_.length() == 0 || this->DirectoryExists()) { + return true; + } + + const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName()); + return parent.CreateDirectoriesRecursively() && this->CreateFolder(); +} + +// Create the directory so that path exists. Returns true if successful or +// if the directory already exists; returns false if unable to create the +// directory for any reason, including if the parent directory does not +// exist. Not named "CreateDirectory" because that's a macro on Windows. +bool FilePath::CreateFolder() const { +#if GTEST_OS_WINDOWS_MOBILE + FilePath removed_sep(this->RemoveTrailingPathSeparator()); + LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str()); + int result = CreateDirectory(unicode, NULL) ? 0 : -1; + delete [] unicode; +#elif GTEST_OS_WINDOWS + int result = _mkdir(pathname_.c_str()); +#else + int result = mkdir(pathname_.c_str(), 0777); +#endif // GTEST_OS_WINDOWS_MOBILE + + if (result == -1) { + return this->DirectoryExists(); // An error is OK if the directory exists. + } + return true; // No error. +} + +// If input name has a trailing separator character, remove it and return the +// name, otherwise return the name string unmodified. +// On Windows platform, uses \ as the separator, other platforms use /. +FilePath FilePath::RemoveTrailingPathSeparator() const { + return IsDirectory() + ? FilePath(pathname_.substr(0, pathname_.length() - 1)) + : *this; +} + +// Removes any redundant separators that might be in the pathname. +// For example, "bar///foo" becomes "bar/foo". Does not eliminate other +// redundancies that might be in a pathname involving "." or "..". +// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share). +void FilePath::Normalize() { + if (pathname_.c_str() == NULL) { + pathname_ = ""; + return; + } + const char* src = pathname_.c_str(); + char* const dest = new char[pathname_.length() + 1]; + char* dest_ptr = dest; + memset(dest_ptr, 0, pathname_.length() + 1); + + while (*src != '\0') { + *dest_ptr = *src; + if (!IsPathSeparator(*src)) { + src++; + } else { +#if GTEST_HAS_ALT_PATH_SEP_ + if (*dest_ptr == kAlternatePathSeparator) { + *dest_ptr = kPathSeparator; + } +#endif + while (IsPathSeparator(*src)) + src++; + } + dest_ptr++; + } + *dest_ptr = '\0'; + pathname_ = dest; + delete[] dest; +} + +} // namespace internal +} // namespace testing +// Copyright 2008, 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 +#include +#include +#include + +#if GTEST_OS_WINDOWS_MOBILE +# include // For TerminateProcess() +#elif GTEST_OS_WINDOWS +# include +# include +#else +# include +#endif // GTEST_OS_WINDOWS_MOBILE + +#if GTEST_OS_MAC +# include +# include +# include +#endif // GTEST_OS_MAC + +#if GTEST_OS_QNX +# include +# include +#endif // GTEST_OS_QNX + + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +#undef GTEST_IMPLEMENTATION_ + +namespace testing { +namespace internal { + +#if defined(_MSC_VER) || defined(__BORLANDC__) +// MSVC and C++Builder do not provide a definition of STDERR_FILENO. +const int kStdOutFileno = 1; +const int kStdErrFileno = 2; +#else +const int kStdOutFileno = STDOUT_FILENO; +const int kStdErrFileno = STDERR_FILENO; +#endif // _MSC_VER + +#if GTEST_OS_MAC + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +size_t GetThreadCount() { + const task_t task = mach_task_self(); + mach_msg_type_number_t thread_count; + thread_act_array_t thread_list; + const kern_return_t status = task_threads(task, &thread_list, &thread_count); + if (status == KERN_SUCCESS) { + // task_threads allocates resources in thread_list and we need to free them + // to avoid leaks. + vm_deallocate(task, + reinterpret_cast(thread_list), + sizeof(thread_t) * thread_count); + return static_cast(thread_count); + } else { + return 0; + } +} + +#elif GTEST_OS_QNX + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +size_t GetThreadCount() { + const int fd = open("/proc/self/as", O_RDONLY); + if (fd < 0) { + return 0; + } + procfs_info process_info; + const int status = + devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), NULL); + close(fd); + if (status == EOK) { + return static_cast(process_info.num_threads); + } else { + return 0; + } +} + +#else + +size_t GetThreadCount() { + // There's no portable way to detect the number of threads, so we just + // return 0 to indicate that we cannot detect it. + return 0; +} + +#endif // GTEST_OS_MAC + +#if GTEST_USES_POSIX_RE + +// Implements RE. Currently only needed for death tests. + +RE::~RE() { + if (is_valid_) { + // regfree'ing an invalid regex might crash because the content + // of the regex is undefined. Since the regex's are essentially + // the same, one cannot be valid (or invalid) without the other + // being so too. + regfree(&partial_regex_); + regfree(&full_regex_); + } + free(const_cast(pattern_)); +} + +// Returns true iff regular expression re matches the entire str. +bool RE::FullMatch(const char* str, const RE& re) { + if (!re.is_valid_) return false; + + regmatch_t match; + return regexec(&re.full_regex_, str, 1, &match, 0) == 0; +} + +// Returns true iff regular expression re matches a substring of str +// (including str itself). +bool RE::PartialMatch(const char* str, const RE& re) { + if (!re.is_valid_) return false; + + regmatch_t match; + return regexec(&re.partial_regex_, str, 1, &match, 0) == 0; +} + +// Initializes an RE from its string representation. +void RE::Init(const char* regex) { + pattern_ = posix::StrDup(regex); + + // Reserves enough bytes to hold the regular expression used for a + // full match. + const size_t full_regex_len = strlen(regex) + 10; + char* const full_pattern = new char[full_regex_len]; + + snprintf(full_pattern, full_regex_len, "^(%s)$", regex); + is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0; + // We want to call regcomp(&partial_regex_, ...) even if the + // previous expression returns false. Otherwise partial_regex_ may + // not be properly initialized can may cause trouble when it's + // freed. + // + // Some implementation of POSIX regex (e.g. on at least some + // versions of Cygwin) doesn't accept the empty string as a valid + // regex. We change it to an equivalent form "()" to be safe. + if (is_valid_) { + const char* const partial_regex = (*regex == '\0') ? "()" : regex; + is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0; + } + EXPECT_TRUE(is_valid_) + << "Regular expression \"" << regex + << "\" is not a valid POSIX Extended regular expression."; + + delete[] full_pattern; +} + +#elif GTEST_USES_SIMPLE_RE + +// Returns true iff ch appears anywhere in str (excluding the +// terminating '\0' character). +bool IsInSet(char ch, const char* str) { + return ch != '\0' && strchr(str, ch) != NULL; +} + +// Returns true iff ch belongs to the given classification. Unlike +// similar functions in , these aren't affected by the +// current locale. +bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; } +bool IsAsciiPunct(char ch) { + return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~"); +} +bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); } +bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); } +bool IsAsciiWordChar(char ch) { + return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || + ('0' <= ch && ch <= '9') || ch == '_'; +} + +// Returns true iff "\\c" is a supported escape sequence. +bool IsValidEscape(char c) { + return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW")); +} + +// Returns true iff the given atom (specified by escaped and pattern) +// matches ch. The result is undefined if the atom is invalid. +bool AtomMatchesChar(bool escaped, char pattern_char, char ch) { + if (escaped) { // "\\p" where p is pattern_char. + switch (pattern_char) { + case 'd': return IsAsciiDigit(ch); + case 'D': return !IsAsciiDigit(ch); + case 'f': return ch == '\f'; + case 'n': return ch == '\n'; + case 'r': return ch == '\r'; + case 's': return IsAsciiWhiteSpace(ch); + case 'S': return !IsAsciiWhiteSpace(ch); + case 't': return ch == '\t'; + case 'v': return ch == '\v'; + case 'w': return IsAsciiWordChar(ch); + case 'W': return !IsAsciiWordChar(ch); + } + return IsAsciiPunct(pattern_char) && pattern_char == ch; + } + + return (pattern_char == '.' && ch != '\n') || pattern_char == ch; +} + +// Helper function used by ValidateRegex() to format error messages. +std::string FormatRegexSyntaxError(const char* regex, int index) { + return (Message() << "Syntax error at index " << index + << " in simple regular expression \"" << regex << "\": ").GetString(); +} + +// Generates non-fatal failures and returns false if regex is invalid; +// otherwise returns true. +bool ValidateRegex(const char* regex) { + if (regex == NULL) { + // TODO(wan@google.com): fix the source file location in the + // assertion failures to match where the regex is used in user + // code. + ADD_FAILURE() << "NULL is not a valid simple regular expression."; + return false; + } + + bool is_valid = true; + + // True iff ?, *, or + can follow the previous atom. + bool prev_repeatable = false; + for (int i = 0; regex[i]; i++) { + if (regex[i] == '\\') { // An escape sequence + i++; + if (regex[i] == '\0') { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) + << "'\\' cannot appear at the end."; + return false; + } + + if (!IsValidEscape(regex[i])) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) + << "invalid escape sequence \"\\" << regex[i] << "\"."; + is_valid = false; + } + prev_repeatable = true; + } else { // Not an escape sequence. + const char ch = regex[i]; + + if (ch == '^' && i > 0) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'^' can only appear at the beginning."; + is_valid = false; + } else if (ch == '$' && regex[i + 1] != '\0') { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'$' can only appear at the end."; + is_valid = false; + } else if (IsInSet(ch, "()[]{}|")) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'" << ch << "' is unsupported."; + is_valid = false; + } else if (IsRepeat(ch) && !prev_repeatable) { + ADD_FAILURE() << FormatRegexSyntaxError(regex, i) + << "'" << ch << "' can only follow a repeatable token."; + is_valid = false; + } + + prev_repeatable = !IsInSet(ch, "^$?*+"); + } + } + + return is_valid; +} + +// Matches a repeated regex atom followed by a valid simple regular +// expression. The regex atom is defined as c if escaped is false, +// or \c otherwise. repeat is the repetition meta character (?, *, +// or +). The behavior is undefined if str contains too many +// characters to be indexable by size_t, in which case the test will +// probably time out anyway. We are fine with this limitation as +// std::string has it too. +bool MatchRepetitionAndRegexAtHead( + bool escaped, char c, char repeat, const char* regex, + const char* str) { + const size_t min_count = (repeat == '+') ? 1 : 0; + const size_t max_count = (repeat == '?') ? 1 : + static_cast(-1) - 1; + // We cannot call numeric_limits::max() as it conflicts with the + // max() macro on Windows. + + for (size_t i = 0; i <= max_count; ++i) { + // We know that the atom matches each of the first i characters in str. + if (i >= min_count && MatchRegexAtHead(regex, str + i)) { + // We have enough matches at the head, and the tail matches too. + // Since we only care about *whether* the pattern matches str + // (as opposed to *how* it matches), there is no need to find a + // greedy match. + return true; + } + if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i])) + return false; + } + return false; +} + +// Returns true iff regex matches a prefix of str. regex must be a +// valid simple regular expression and not start with "^", or the +// result is undefined. +bool MatchRegexAtHead(const char* regex, const char* str) { + if (*regex == '\0') // An empty regex matches a prefix of anything. + return true; + + // "$" only matches the end of a string. Note that regex being + // valid guarantees that there's nothing after "$" in it. + if (*regex == '$') + return *str == '\0'; + + // Is the first thing in regex an escape sequence? + const bool escaped = *regex == '\\'; + if (escaped) + ++regex; + if (IsRepeat(regex[1])) { + // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so + // here's an indirect recursion. It terminates as the regex gets + // shorter in each recursion. + return MatchRepetitionAndRegexAtHead( + escaped, regex[0], regex[1], regex + 2, str); + } else { + // regex isn't empty, isn't "$", and doesn't start with a + // repetition. We match the first atom of regex with the first + // character of str and recurse. + return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) && + MatchRegexAtHead(regex + 1, str + 1); + } +} + +// Returns true iff regex matches any substring of str. regex must be +// a valid simple regular expression, or the result is undefined. +// +// The algorithm is recursive, but the recursion depth doesn't exceed +// the regex length, so we won't need to worry about running out of +// stack space normally. In rare cases the time complexity can be +// exponential with respect to the regex length + the string length, +// but usually it's must faster (often close to linear). +bool MatchRegexAnywhere(const char* regex, const char* str) { + if (regex == NULL || str == NULL) + return false; + + if (*regex == '^') + return MatchRegexAtHead(regex + 1, str); + + // A successful match can be anywhere in str. + do { + if (MatchRegexAtHead(regex, str)) + return true; + } while (*str++ != '\0'); + return false; +} + +// Implements the RE class. + +RE::~RE() { + free(const_cast(pattern_)); + free(const_cast(full_pattern_)); +} + +// Returns true iff regular expression re matches the entire str. +bool RE::FullMatch(const char* str, const RE& re) { + return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str); +} + +// Returns true iff regular expression re matches a substring of str +// (including str itself). +bool RE::PartialMatch(const char* str, const RE& re) { + return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str); +} + +// Initializes an RE from its string representation. +void RE::Init(const char* regex) { + pattern_ = full_pattern_ = NULL; + if (regex != NULL) { + pattern_ = posix::StrDup(regex); + } + + is_valid_ = ValidateRegex(regex); + if (!is_valid_) { + // No need to calculate the full pattern when the regex is invalid. + return; + } + + const size_t len = strlen(regex); + // Reserves enough bytes to hold the regular expression used for a + // full match: we need space to prepend a '^', append a '$', and + // terminate the string with '\0'. + char* buffer = static_cast(malloc(len + 3)); + full_pattern_ = buffer; + + if (*regex != '^') + *buffer++ = '^'; // Makes sure full_pattern_ starts with '^'. + + // We don't use snprintf or strncpy, as they trigger a warning when + // compiled with VC++ 8.0. + memcpy(buffer, regex, len); + buffer += len; + + if (len == 0 || regex[len - 1] != '$') + *buffer++ = '$'; // Makes sure full_pattern_ ends with '$'. + + *buffer = '\0'; +} + +#endif // GTEST_USES_POSIX_RE + +const char kUnknownFile[] = "unknown file"; + +// Formats a source file path and a line number as they would appear +// in an error message from the compiler used to compile this code. +GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) { + const std::string file_name(file == NULL ? kUnknownFile : file); + + if (line < 0) { + return file_name + ":"; + } +#ifdef _MSC_VER + return file_name + "(" + StreamableToString(line) + "):"; +#else + return file_name + ":" + StreamableToString(line) + ":"; +#endif // _MSC_VER +} + +// Formats a file location for compiler-independent XML output. +// Although this function is not platform dependent, we put it next to +// FormatFileLocation in order to contrast the two functions. +// Note that FormatCompilerIndependentFileLocation() does NOT append colon +// to the file location it produces, unlike FormatFileLocation(). +GTEST_API_ ::std::string FormatCompilerIndependentFileLocation( + const char* file, int line) { + const std::string file_name(file == NULL ? kUnknownFile : file); + + if (line < 0) + return file_name; + else + return file_name + ":" + StreamableToString(line); +} + + +GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line) + : severity_(severity) { + const char* const marker = + severity == GTEST_INFO ? "[ INFO ]" : + severity == GTEST_WARNING ? "[WARNING]" : + severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]"; + GetStream() << ::std::endl << marker << " " + << FormatFileLocation(file, line).c_str() << ": "; +} + +// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. +GTestLog::~GTestLog() { + GetStream() << ::std::endl; + if (severity_ == GTEST_FATAL) { + fflush(stderr); + posix::Abort(); + } +} +// Disable Microsoft deprecation warnings for POSIX functions called from +// this class (creat, dup, dup2, and close) +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4996) +#endif // _MSC_VER + +#if GTEST_HAS_STREAM_REDIRECTION + +// Object that captures an output stream (stdout/stderr). +class CapturedStream { + public: + // The ctor redirects the stream to a temporary file. + explicit CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) { +# if GTEST_OS_WINDOWS + char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT + char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT + + ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path); + const UINT success = ::GetTempFileNameA(temp_dir_path, + "gtest_redir", + 0, // Generate unique file name. + temp_file_path); + GTEST_CHECK_(success != 0) + << "Unable to create a temporary file in " << temp_dir_path; + const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE); + GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file " + << temp_file_path; + filename_ = temp_file_path; +# else + // There's no guarantee that a test has write access to the current + // directory, so we create the temporary file in the /tmp directory + // instead. We use /tmp on most systems, and /sdcard on Android. + // That's because Android doesn't have /tmp. +# if GTEST_OS_LINUX_ANDROID + // Note: Android applications are expected to call the framework's + // Context.getExternalStorageDirectory() method through JNI to get + // the location of the world-writable SD Card directory. However, + // this requires a Context handle, which cannot be retrieved + // globally from native code. Doing so also precludes running the + // code as part of a regular standalone executable, which doesn't + // run in a Dalvik process (e.g. when running it through 'adb shell'). + // + // The location /sdcard is directly accessible from native code + // and is the only location (unofficially) supported by the Android + // team. It's generally a symlink to the real SD Card mount point + // which can be /mnt/sdcard, /mnt/sdcard0, /system/media/sdcard, or + // other OEM-customized locations. Never rely on these, and always + // use /sdcard. + char name_template[] = "/sdcard/gtest_captured_stream.XXXXXX"; +# else + char name_template[] = "/tmp/captured_stream.XXXXXX"; +# endif // GTEST_OS_LINUX_ANDROID + const int captured_fd = mkstemp(name_template); + filename_ = name_template; +# endif // GTEST_OS_WINDOWS + fflush(NULL); + dup2(captured_fd, fd_); + close(captured_fd); + } + + ~CapturedStream() { + remove(filename_.c_str()); + } + + std::string GetCapturedString() { + if (uncaptured_fd_ != -1) { + // Restores the original stream. + fflush(NULL); + dup2(uncaptured_fd_, fd_); + close(uncaptured_fd_); + uncaptured_fd_ = -1; + } + + FILE* const file = posix::FOpen(filename_.c_str(), "r"); + const std::string content = ReadEntireFile(file); + posix::FClose(file); + return content; + } + + private: + // Reads the entire content of a file as an std::string. + static std::string ReadEntireFile(FILE* file); + + // Returns the size (in bytes) of a file. + static size_t GetFileSize(FILE* file); + + const int fd_; // A stream to capture. + int uncaptured_fd_; + // Name of the temporary file holding the stderr output. + ::std::string filename_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream); +}; + +// Returns the size (in bytes) of a file. +size_t CapturedStream::GetFileSize(FILE* file) { + fseek(file, 0, SEEK_END); + return static_cast(ftell(file)); +} + +// Reads the entire content of a file as a string. +std::string CapturedStream::ReadEntireFile(FILE* file) { + const size_t file_size = GetFileSize(file); + char* const buffer = new char[file_size]; + + size_t bytes_last_read = 0; // # of bytes read in the last fread() + size_t bytes_read = 0; // # of bytes read so far + + fseek(file, 0, SEEK_SET); + + // Keeps reading the file until we cannot read further or the + // pre-determined file size is reached. + do { + bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file); + bytes_read += bytes_last_read; + } while (bytes_last_read > 0 && bytes_read < file_size); + + const std::string content(buffer, bytes_read); + delete[] buffer; + + return content; +} + +# ifdef _MSC_VER +# pragma warning(pop) +# endif // _MSC_VER + +static CapturedStream* g_captured_stderr = NULL; +static CapturedStream* g_captured_stdout = NULL; + +// Starts capturing an output stream (stdout/stderr). +void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) { + if (*stream != NULL) { + GTEST_LOG_(FATAL) << "Only one " << stream_name + << " capturer can exist at a time."; + } + *stream = new CapturedStream(fd); +} + +// Stops capturing the output stream and returns the captured string. +std::string GetCapturedStream(CapturedStream** captured_stream) { + const std::string content = (*captured_stream)->GetCapturedString(); + + delete *captured_stream; + *captured_stream = NULL; + + return content; +} + +// Starts capturing stdout. +void CaptureStdout() { + CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout); +} + +// Starts capturing stderr. +void CaptureStderr() { + CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr); +} + +// Stops capturing stdout and returns the captured string. +std::string GetCapturedStdout() { + return GetCapturedStream(&g_captured_stdout); +} + +// Stops capturing stderr and returns the captured string. +std::string GetCapturedStderr() { + return GetCapturedStream(&g_captured_stderr); +} + +#endif // GTEST_HAS_STREAM_REDIRECTION + +#if GTEST_HAS_DEATH_TEST + +// A copy of all command line arguments. Set by InitGoogleTest(). +::std::vector g_argvs; + +static const ::std::vector* g_injected_test_argvs = + NULL; // Owned. + +void SetInjectableArgvs(const ::std::vector* argvs) { + if (g_injected_test_argvs != argvs) + delete g_injected_test_argvs; + g_injected_test_argvs = argvs; +} + +const ::std::vector& GetInjectableArgvs() { + if (g_injected_test_argvs != NULL) { + return *g_injected_test_argvs; + } + return g_argvs; +} +#endif // GTEST_HAS_DEATH_TEST + +#if GTEST_OS_WINDOWS_MOBILE +namespace posix { +void Abort() { + DebugBreak(); + TerminateProcess(GetCurrentProcess(), 1); +} +} // namespace posix +#endif // GTEST_OS_WINDOWS_MOBILE + +// Returns the name of the environment variable corresponding to the +// given flag. For example, FlagToEnvVar("foo") will return +// "GTEST_FOO" in the open-source version. +static std::string FlagToEnvVar(const char* flag) { + const std::string full_flag = + (Message() << GTEST_FLAG_PREFIX_ << flag).GetString(); + + Message env_var; + for (size_t i = 0; i != full_flag.length(); i++) { + env_var << ToUpper(full_flag.c_str()[i]); + } + + return env_var.GetString(); +} + +// Parses 'str' for a 32-bit signed integer. If successful, writes +// the result to *value and returns true; otherwise leaves *value +// unchanged and returns false. +bool ParseInt32(const Message& src_text, const char* str, Int32* value) { + // Parses the environment variable as a decimal integer. + char* end = NULL; + const long long_value = strtol(str, &end, 10); // NOLINT + + // Has strtol() consumed all characters in the string? + if (*end != '\0') { + // No - an invalid character was encountered. + Message msg; + msg << "WARNING: " << src_text + << " is expected to be a 32-bit integer, but actually" + << " has value \"" << str << "\".\n"; + printf("%s", msg.GetString().c_str()); + fflush(stdout); + return false; + } + + // Is the parsed value in the range of an Int32? + const Int32 result = static_cast(long_value); + if (long_value == LONG_MAX || long_value == LONG_MIN || + // The parsed value overflows as a long. (strtol() returns + // LONG_MAX or LONG_MIN when the input overflows.) + result != long_value + // The parsed value overflows as an Int32. + ) { + Message msg; + msg << "WARNING: " << src_text + << " is expected to be a 32-bit integer, but actually" + << " has value " << str << ", which overflows.\n"; + printf("%s", msg.GetString().c_str()); + fflush(stdout); + return false; + } + + *value = result; + return true; +} + +// Reads and returns the Boolean environment variable corresponding to +// the given flag; if it's not set, returns default_value. +// +// The value is considered true iff it's not "0". +bool BoolFromGTestEnv(const char* flag, bool default_value) { + const std::string env_var = FlagToEnvVar(flag); + const char* const string_value = posix::GetEnv(env_var.c_str()); + return string_value == NULL ? + default_value : strcmp(string_value, "0") != 0; +} + +// Reads and returns a 32-bit integer stored in the environment +// variable corresponding to the given flag; if it isn't set or +// doesn't represent a valid 32-bit integer, returns default_value. +Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) { + const std::string env_var = FlagToEnvVar(flag); + const char* const string_value = posix::GetEnv(env_var.c_str()); + if (string_value == NULL) { + // The environment variable is not set. + return default_value; + } + + Int32 result = default_value; + if (!ParseInt32(Message() << "Environment variable " << env_var, + string_value, &result)) { + printf("The default value %s is used.\n", + (Message() << default_value).GetString().c_str()); + fflush(stdout); + return default_value; + } + + return result; +} + +// Reads and returns the string environment variable corresponding to +// the given flag; if it's not set, returns default_value. +const char* StringFromGTestEnv(const char* flag, const char* default_value) { + const std::string env_var = FlagToEnvVar(flag); + const char* const value = posix::GetEnv(env_var.c_str()); + return value == NULL ? default_value : value; +} + +} // namespace internal +} // namespace testing +// 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) + +// Google Test - The Google C++ Testing Framework +// +// This file implements a universal value printer that can print a +// value of any type T: +// +// void ::testing::internal::UniversalPrinter::Print(value, ostream_ptr); +// +// It uses the << operator when possible, and prints the bytes in the +// object otherwise. A user can override its behavior for a class +// type Foo by defining either operator<<(::std::ostream&, const Foo&) +// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that +// defines Foo. + +#include +#include +#include // NOLINT +#include + +namespace testing { + +namespace { + +using ::std::ostream; + +// Prints a segment of bytes in the given object. +void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start, + size_t count, ostream* os) { + char text[5] = ""; + for (size_t i = 0; i != count; i++) { + const size_t j = start + i; + if (i != 0) { + // Organizes the bytes into groups of 2 for easy parsing by + // human. + if ((j % 2) == 0) + *os << ' '; + else + *os << '-'; + } + GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]); + *os << text; + } +} + +// Prints the bytes in the given value to the given ostream. +void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count, + ostream* os) { + // Tells the user how big the object is. + *os << count << "-byte object <"; + + const size_t kThreshold = 132; + const size_t kChunkSize = 64; + // If the object size is bigger than kThreshold, we'll have to omit + // some details by printing only the first and the last kChunkSize + // bytes. + // TODO(wan): let the user control the threshold using a flag. + if (count < kThreshold) { + PrintByteSegmentInObjectTo(obj_bytes, 0, count, os); + } else { + PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os); + *os << " ... "; + // Rounds up to 2-byte boundary. + const size_t resume_pos = (count - kChunkSize + 1)/2*2; + PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os); + } + *os << ">"; +} + +} // namespace + +namespace internal2 { + +// Delegates to PrintBytesInObjectToImpl() to print the bytes in the +// given object. The delegation simplifies the implementation, which +// uses the << operator and thus is easier done outside of the +// ::testing::internal namespace, which contains a << operator that +// sometimes conflicts with the one in STL. +void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count, + ostream* os) { + PrintBytesInObjectToImpl(obj_bytes, count, os); +} + +} // namespace internal2 + +namespace internal { + +// Depending on the value of a char (or wchar_t), we print it in one +// of three formats: +// - as is if it's a printable ASCII (e.g. 'a', '2', ' '), +// - as a hexidecimal escape sequence (e.g. '\x7F'), or +// - as a special escape sequence (e.g. '\r', '\n'). +enum CharFormat { + kAsIs, + kHexEscape, + kSpecialEscape +}; + +// Returns true if c is a printable ASCII character. We test the +// value of c directly instead of calling isprint(), which is buggy on +// Windows Mobile. +inline bool IsPrintableAscii(wchar_t c) { + return 0x20 <= c && c <= 0x7E; +} + +// Prints a wide or narrow char c as a character literal without the +// quotes, escaping it when necessary; returns how c was formatted. +// The template argument UnsignedChar is the unsigned version of Char, +// which is the type of c. +template +static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) { + switch (static_cast(c)) { + case L'\0': + *os << "\\0"; + break; + case L'\'': + *os << "\\'"; + break; + case L'\\': + *os << "\\\\"; + break; + case L'\a': + *os << "\\a"; + break; + case L'\b': + *os << "\\b"; + break; + case L'\f': + *os << "\\f"; + break; + case L'\n': + *os << "\\n"; + break; + case L'\r': + *os << "\\r"; + break; + case L'\t': + *os << "\\t"; + break; + case L'\v': + *os << "\\v"; + break; + default: + if (IsPrintableAscii(c)) { + *os << static_cast(c); + return kAsIs; + } else { + *os << "\\x" + String::FormatHexInt(static_cast(c)); + return kHexEscape; + } + } + return kSpecialEscape; +} + +// Prints a wchar_t c as if it's part of a string literal, escaping it when +// necessary; returns how c was formatted. +static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) { + switch (c) { + case L'\'': + *os << "'"; + return kAsIs; + case L'"': + *os << "\\\""; + return kSpecialEscape; + default: + return PrintAsCharLiteralTo(c, os); + } +} + +// Prints a char c as if it's part of a string literal, escaping it when +// necessary; returns how c was formatted. +static CharFormat PrintAsStringLiteralTo(char c, ostream* os) { + return PrintAsStringLiteralTo( + static_cast(static_cast(c)), os); +} + +// Prints a wide or narrow character c and its code. '\0' is printed +// as "'\\0'", other unprintable characters are also properly escaped +// using the standard C++ escape sequence. The template argument +// UnsignedChar is the unsigned version of Char, which is the type of c. +template +void PrintCharAndCodeTo(Char c, ostream* os) { + // First, print c as a literal in the most readable form we can find. + *os << ((sizeof(c) > 1) ? "L'" : "'"); + const CharFormat format = PrintAsCharLiteralTo(c, os); + *os << "'"; + + // To aid user debugging, we also print c's code in decimal, unless + // it's 0 (in which case c was printed as '\\0', making the code + // obvious). + if (c == 0) + return; + *os << " (" << static_cast(c); + + // For more convenience, we print c's code again in hexidecimal, + // unless c was already printed in the form '\x##' or the code is in + // [1, 9]. + if (format == kHexEscape || (1 <= c && c <= 9)) { + // Do nothing. + } else { + *os << ", 0x" << String::FormatHexInt(static_cast(c)); + } + *os << ")"; +} + +void PrintTo(unsigned char c, ::std::ostream* os) { + PrintCharAndCodeTo(c, os); +} +void PrintTo(signed char c, ::std::ostream* os) { + PrintCharAndCodeTo(c, os); +} + +// Prints a wchar_t as a symbol if it is printable or as its internal +// code otherwise and also as its code. L'\0' is printed as "L'\\0'". +void PrintTo(wchar_t wc, ostream* os) { + PrintCharAndCodeTo(wc, os); +} + +// Prints the given array of characters to the ostream. CharType must be either +// char or wchar_t. +// The array starts at begin, the length is len, it may include '\0' characters +// and may not be NUL-terminated. +template +static void PrintCharsAsStringTo( + const CharType* begin, size_t len, ostream* os) { + const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\""; + *os << kQuoteBegin; + bool is_previous_hex = false; + for (size_t index = 0; index < len; ++index) { + const CharType cur = begin[index]; + if (is_previous_hex && IsXDigit(cur)) { + // Previous character is of '\x..' form and this character can be + // interpreted as another hexadecimal digit in its number. Break string to + // disambiguate. + *os << "\" " << kQuoteBegin; + } + is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape; + } + *os << "\""; +} + +// Prints a (const) char/wchar_t array of 'len' elements, starting at address +// 'begin'. CharType must be either char or wchar_t. +template +static void UniversalPrintCharArray( + const CharType* begin, size_t len, ostream* os) { + // The code + // const char kFoo[] = "foo"; + // generates an array of 4, not 3, elements, with the last one being '\0'. + // + // Therefore when printing a char array, we don't print the last element if + // it's '\0', such that the output matches the string literal as it's + // written in the source code. + if (len > 0 && begin[len - 1] == '\0') { + PrintCharsAsStringTo(begin, len - 1, os); + return; + } + + // If, however, the last element in the array is not '\0', e.g. + // const char kFoo[] = { 'f', 'o', 'o' }; + // we must print the entire array. We also print a message to indicate + // that the array is not NUL-terminated. + PrintCharsAsStringTo(begin, len, os); + *os << " (no terminating NUL)"; +} + +// Prints a (const) char array of 'len' elements, starting at address 'begin'. +void UniversalPrintArray(const char* begin, size_t len, ostream* os) { + UniversalPrintCharArray(begin, len, os); +} + +// Prints a (const) wchar_t array of 'len' elements, starting at address +// 'begin'. +void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) { + UniversalPrintCharArray(begin, len, os); +} + +// Prints the given C string to the ostream. +void PrintTo(const char* s, ostream* os) { + if (s == NULL) { + *os << "NULL"; + } else { + *os << ImplicitCast_(s) << " pointing to "; + PrintCharsAsStringTo(s, strlen(s), os); + } +} + +// MSVC compiler can be configured to define whar_t as a typedef +// of unsigned short. Defining an overload for const wchar_t* in that case +// would cause pointers to unsigned shorts be printed as wide strings, +// possibly accessing more memory than intended and causing invalid +// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when +// wchar_t is implemented as a native type. +#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) +// Prints the given wide C string to the ostream. +void PrintTo(const wchar_t* s, ostream* os) { + if (s == NULL) { + *os << "NULL"; + } else { + *os << ImplicitCast_(s) << " pointing to "; + PrintCharsAsStringTo(s, wcslen(s), os); + } +} +#endif // wchar_t is native + +// Prints a ::string object. +#if GTEST_HAS_GLOBAL_STRING +void PrintStringTo(const ::string& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_GLOBAL_STRING + +void PrintStringTo(const ::std::string& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} + +// Prints a ::wstring object. +#if GTEST_HAS_GLOBAL_WSTRING +void PrintWideStringTo(const ::wstring& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_GLOBAL_WSTRING + +#if GTEST_HAS_STD_WSTRING +void PrintWideStringTo(const ::std::wstring& s, ostream* os) { + PrintCharsAsStringTo(s.data(), s.size(), os); +} +#endif // GTEST_HAS_STD_WSTRING + +} // namespace internal + +} // namespace testing +// Copyright 2008, 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: mheule@google.com (Markus Heule) +// +// The Google C++ Testing Framework (Google Test) + + +// Indicates that this translation unit is part of Google Test's +// implementation. It must come before gtest-internal-inl.h is +// included, or there will be a compiler error. This trick is to +// prevent a user from accidentally including gtest-internal-inl.h in +// his code. +#define GTEST_IMPLEMENTATION_ 1 +#undef GTEST_IMPLEMENTATION_ + +namespace testing { + +using internal::GetUnitTestImpl; + +// Gets the summary of the failure message by omitting the stack trace +// in it. +std::string TestPartResult::ExtractSummary(const char* message) { + const char* const stack_trace = strstr(message, internal::kStackTraceMarker); + return stack_trace == NULL ? message : + std::string(message, stack_trace); +} + +// Prints a TestPartResult object. +std::ostream& operator<<(std::ostream& os, const TestPartResult& result) { + return os + << result.file_name() << ":" << result.line_number() << ": " + << (result.type() == TestPartResult::kSuccess ? "Success" : + result.type() == TestPartResult::kFatalFailure ? "Fatal failure" : + "Non-fatal failure") << ":\n" + << result.message() << std::endl; +} + +// Appends a TestPartResult to the array. +void TestPartResultArray::Append(const TestPartResult& result) { + array_.push_back(result); +} + +// Returns the TestPartResult at the given index (0-based). +const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const { + if (index < 0 || index >= size()) { + printf("\nInvalid index (%d) into TestPartResultArray.\n", index); + internal::posix::Abort(); + } + + return array_[index]; +} + +// Returns the number of TestPartResult objects in the array. +int TestPartResultArray::size() const { + return static_cast(array_.size()); +} + +namespace internal { + +HasNewFatalFailureHelper::HasNewFatalFailureHelper() + : has_new_fatal_failure_(false), + original_reporter_(GetUnitTestImpl()-> + GetTestPartResultReporterForCurrentThread()) { + GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this); +} + +HasNewFatalFailureHelper::~HasNewFatalFailureHelper() { + GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread( + original_reporter_); +} + +void HasNewFatalFailureHelper::ReportTestPartResult( + const TestPartResult& result) { + if (result.fatally_failed()) + has_new_fatal_failure_ = true; + original_reporter_->ReportTestPartResult(result); +} + +} // namespace internal + +} // namespace testing +// Copyright 2008 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) + + +namespace testing { +namespace internal { + +#if GTEST_HAS_TYPED_TEST_P + +// Skips to the first non-space char in str. Returns an empty string if str +// contains only whitespace characters. +static const char* SkipSpaces(const char* str) { + while (IsSpace(*str)) + str++; + return str; +} + +// Verifies that registered_tests match the test names in +// defined_test_names_; returns registered_tests if successful, or +// aborts the program otherwise. +const char* TypedTestCasePState::VerifyRegisteredTestNames( + const char* file, int line, const char* registered_tests) { + typedef ::std::set::const_iterator DefinedTestIter; + registered_ = true; + + // Skip initial whitespace in registered_tests since some + // preprocessors prefix stringizied literals with whitespace. + registered_tests = SkipSpaces(registered_tests); + + Message errors; + ::std::set tests; + for (const char* names = registered_tests; names != NULL; + names = SkipComma(names)) { + const std::string name = GetPrefixUntilComma(names); + if (tests.count(name) != 0) { + errors << "Test " << name << " is listed more than once.\n"; + continue; + } + + bool found = false; + for (DefinedTestIter it = defined_test_names_.begin(); + it != defined_test_names_.end(); + ++it) { + if (name == *it) { + found = true; + break; + } + } + + if (found) { + tests.insert(name); + } else { + errors << "No test named " << name + << " can be found in this test case.\n"; + } + } + + for (DefinedTestIter it = defined_test_names_.begin(); + it != defined_test_names_.end(); + ++it) { + if (tests.count(*it) == 0) { + errors << "You forgot to list test " << *it << ".\n"; + } + } + + const std::string& errors_str = errors.GetString(); + if (errors_str != "") { + fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), + errors_str.c_str()); + fflush(stderr); + posix::Abort(); + } + + return registered_tests; +} + +#endif // GTEST_HAS_TYPED_TEST_P + +} // namespace internal +} // namespace testing diff --git a/ZaharovaDD/lab2/gtest/gtest.h b/ZaharovaDD/lab2/gtest/gtest.h new file mode 100644 index 000000000..6e7cfc2be --- /dev/null +++ b/ZaharovaDD/lab2/gtest/gtest.h @@ -0,0 +1,20063 @@ +// 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 +// 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) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines the public API for Google Test. It should be +// included by any test program that uses Google Test. +// +// IMPORTANT NOTE: Due to limitation of the C++ language, we have to +// leave some internal implementation details in this header file. +// They are clearly marked by comments like this: +// +// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +// +// Such code is NOT meant to be used by a user directly, and is subject +// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user +// program! +// +// Acknowledgment: Google Test borrowed the idea of automatic test +// registration from Barthelemy Dagenais' (barthelemy@prologique.com) +// easyUnit framework. + +#define _VARIADIC_MAX 10 + +#ifndef GTEST_INCLUDE_GTEST_GTEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_H_ + +#include +#include +#include + +// 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 +// 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. +// +// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file declares functions and macros used internally by +// Google Test. They are subject to change without notice. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ + +// 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 +// 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. +// +// Authors: wan@google.com (Zhanyong Wan) +// +// Low-level types and utilities for porting Google Test to various +// platforms. They are subject to change without notice. DO NOT USE +// THEM IN USER CODE. +// +// This file is fundamental to Google Test. All other Google Test source +// files are expected to #include this. Therefore, it cannot #include +// any other Google Test header. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ + +// The user can define the following macros in the build script to +// control Google Test's behavior. If the user doesn't define a macro +// in this list, Google Test will define it. +// +// GTEST_HAS_CLONE - Define it to 1/0 to indicate that clone(2) +// is/isn't available. +// GTEST_HAS_EXCEPTIONS - Define it to 1/0 to indicate that exceptions +// are enabled. +// GTEST_HAS_GLOBAL_STRING - Define it to 1/0 to indicate that ::string +// is/isn't available (some systems define +// ::string, which is different to std::string). +// GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::string +// is/isn't available (some systems define +// ::wstring, which is different to std::wstring). +// GTEST_HAS_POSIX_RE - Define it to 1/0 to indicate that POSIX regular +// expressions are/aren't available. +// GTEST_HAS_PTHREAD - Define it to 1/0 to indicate that +// is/isn't available. +// GTEST_HAS_RTTI - Define it to 1/0 to indicate that RTTI is/isn't +// enabled. +// 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 - 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_HAS_STREAM_REDIRECTION +// - Define it to 1/0 to indicate whether the +// platform supports I/O stream redirection using +// dup() and dup2(). +// 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. +// GTEST_LANG_CXX11 - Define it to 1/0 to indicate that Google Test +// is building in C++11/C++98 mode. +// GTEST_LINKED_AS_SHARED_LIBRARY +// - Define to 1 when compiling tests that use +// Google Test as a shared library (known as +// DLL on Windows). +// GTEST_CREATE_SHARED_LIBRARY +// - Define to 1 when compiling Google Test itself +// as a shared library. + +// This header defines the following utilities: +// +// Macros indicating the current platform (defined to 1 if compiled on +// the given platform; otherwise undefined): +// GTEST_OS_AIX - IBM AIX +// GTEST_OS_CYGWIN - Cygwin +// GTEST_OS_HPUX - HP-UX +// GTEST_OS_LINUX - Linux +// GTEST_OS_LINUX_ANDROID - Google Android +// GTEST_OS_MAC - Mac OS X +// GTEST_OS_IOS - iOS +// GTEST_OS_IOS_SIMULATOR - iOS simulator +// GTEST_OS_NACL - Google Native Client (NaCl) +// GTEST_OS_OPENBSD - OpenBSD +// GTEST_OS_QNX - QNX +// GTEST_OS_SOLARIS - Sun Solaris +// GTEST_OS_SYMBIAN - Symbian +// GTEST_OS_WINDOWS - Windows (Desktop, MinGW, or Mobile) +// GTEST_OS_WINDOWS_DESKTOP - Windows Desktop +// GTEST_OS_WINDOWS_MINGW - MinGW +// GTEST_OS_WINDOWS_MOBILE - Windows Mobile +// GTEST_OS_ZOS - z/OS +// +// Among the platforms, Cygwin, Linux, Max OS X, and Windows have the +// most stable support. Since core members of the Google Test project +// don't have access to other platforms, support for them may be less +// stable. If you notice any problems on your platform, please notify +// googletestframework@googlegroups.com (patches for fixing them are +// even more welcome!). +// +// Note that it is possible that none of the GTEST_OS_* macros are defined. +// +// Macros indicating available Google Test features (defined to 1 if +// the corresponding feature is supported; otherwise undefined): +// GTEST_HAS_COMBINE - the Combine() function (for value-parameterized +// tests) +// GTEST_HAS_DEATH_TEST - death tests +// GTEST_HAS_PARAM_TEST - value-parameterized tests +// GTEST_HAS_TYPED_TEST - typed tests +// GTEST_HAS_TYPED_TEST_P - type-parameterized tests +// GTEST_USES_POSIX_RE - enhanced POSIX regex is used. Do not confuse with +// GTEST_HAS_POSIX_RE (see above) which users can +// define themselves. +// GTEST_USES_SIMPLE_RE - our own simple regex is used; +// the above two are mutually exclusive. +// GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ(). +// +// Macros for basic C++ coding: +// GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning. +// GTEST_ATTRIBUTE_UNUSED_ - declares that a class' instances or a +// variable don't have to be used. +// GTEST_DISALLOW_ASSIGN_ - disables operator=. +// GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=. +// GTEST_MUST_USE_RESULT_ - declares that a function's result must be used. +// +// Synchronization: +// Mutex, MutexLock, ThreadLocal, GetThreadCount() +// - synchronization primitives. +// GTEST_IS_THREADSAFE - defined to 1 to indicate that the above +// synchronization primitives have real implementations +// and Google Test is thread-safe; or 0 otherwise. +// +// Template meta programming: +// is_pointer - as in TR1; needed on Symbian and IBM XL C/C++ only. +// IteratorTraits - partial implementation of std::iterator_traits, which +// is not available in libCstd when compiled with Sun C++. +// +// Smart pointers: +// scoped_ptr - as in TR2. +// +// Regular expressions: +// RE - a simple regular expression class using the POSIX +// Extended Regular Expression syntax on UNIX-like +// platforms, or a reduced regular exception syntax on +// other platforms, including Windows. +// +// Logging: +// GTEST_LOG_() - logs messages at the specified severity level. +// LogToStderr() - directs all log messages to stderr. +// FlushInfoLog() - flushes informational log messages. +// +// Stdout and stderr capturing: +// CaptureStdout() - starts capturing stdout. +// GetCapturedStdout() - stops capturing stdout and returns the captured +// string. +// CaptureStderr() - starts capturing stderr. +// GetCapturedStderr() - stops capturing stderr and returns the captured +// string. +// +// Integer types: +// TypeWithSize - maps an integer to a int type. +// Int32, UInt32, Int64, UInt64, TimeInMillis +// - integers of known sizes. +// BiggestInt - the biggest signed integer type. +// +// Command-line utilities: +// GTEST_FLAG() - references a flag. +// GTEST_DECLARE_*() - declares a flag. +// GTEST_DEFINE_*() - defines a flag. +// GetInjectableArgvs() - returns the command line as a vector of strings. +// +// Environment variable utilities: +// GetEnv() - gets the value of an environment variable. +// BoolFromGTestEnv() - parses a bool environment variable. +// Int32FromGTestEnv() - parses an Int32 environment variable. +// StringFromGTestEnv() - parses a string environment variable. + +#include // for isspace, etc +#include // for ptrdiff_t +#include +#include +#include +#ifndef _WIN32_WCE +# include +# include +#endif // !_WIN32_WCE + +#if defined __APPLE__ +# include +# include +#endif + +#include // NOLINT +#include // NOLINT +#include // NOLINT + +#define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com" +#define GTEST_FLAG_PREFIX_ "gtest_" +#define GTEST_FLAG_PREFIX_DASH_ "gtest-" +#define GTEST_FLAG_PREFIX_UPPER_ "GTEST_" +#define GTEST_NAME_ "Google Test" +#define GTEST_PROJECT_URL_ "http://code.google.com/p/googletest/" + +// Determines the version of gcc that is used to compile this. +#ifdef __GNUC__ +// 40302 means version 4.3.2. +# define GTEST_GCC_VER_ \ + (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__) +#endif // __GNUC__ + +// Determines the platform on which Google Test is compiled. +#ifdef __CYGWIN__ +# define GTEST_OS_CYGWIN 1 +#elif defined __SYMBIAN32__ +# define GTEST_OS_SYMBIAN 1 +#elif defined _WIN32 +# define GTEST_OS_WINDOWS 1 +# ifdef _WIN32_WCE +# define GTEST_OS_WINDOWS_MOBILE 1 +# elif defined(__MINGW__) || defined(__MINGW32__) +# define GTEST_OS_WINDOWS_MINGW 1 +# else +# define GTEST_OS_WINDOWS_DESKTOP 1 +# endif // _WIN32_WCE +#elif defined __APPLE__ +# define GTEST_OS_MAC 1 +# if TARGET_OS_IPHONE +# define GTEST_OS_IOS 1 +# if TARGET_IPHONE_SIMULATOR +# define GTEST_OS_IOS_SIMULATOR 1 +# endif +# endif +#elif defined __linux__ +# define GTEST_OS_LINUX 1 +# if defined __ANDROID__ +# define GTEST_OS_LINUX_ANDROID 1 +# endif +#elif defined __MVS__ +# define GTEST_OS_ZOS 1 +#elif defined(__sun) && defined(__SVR4) +# define GTEST_OS_SOLARIS 1 +#elif defined(_AIX) +# define GTEST_OS_AIX 1 +#elif defined(__hpux) +# define GTEST_OS_HPUX 1 +#elif defined __native_client__ +# define GTEST_OS_NACL 1 +#elif defined __OpenBSD__ +# define GTEST_OS_OPENBSD 1 +#elif defined __QNX__ +# define GTEST_OS_QNX 1 +#endif // __CYGWIN__ + +#ifndef GTEST_LANG_CXX11 +// gcc and clang define __GXX_EXPERIMENTAL_CXX0X__ when +// -std={c,gnu}++{0x,11} is passed. The C++11 standard specifies a +// value for __cplusplus, and recent versions of clang, gcc, and +// probably other compilers set that too in C++11 mode. +# if __GXX_EXPERIMENTAL_CXX0X__ || __cplusplus >= 201103L +// Compiling in at least C++11 mode. +# define GTEST_LANG_CXX11 1 +# else +# define GTEST_LANG_CXX11 0 +# endif +#endif + +// Brings in definitions for functions used in the testing::internal::posix +// namespace (read, write, close, chdir, isatty, stat). We do not currently +// use them on Windows Mobile. +#if !GTEST_OS_WINDOWS +// This assumes that non-Windows OSes provide unistd.h. For OSes where this +// is not the case, we need to include headers that provide the functions +// mentioned above. +# include +# include +#elif !GTEST_OS_WINDOWS_MOBILE +# include +# include +#endif + +#if GTEST_OS_LINUX_ANDROID +// Used to define __ANDROID_API__ matching the target NDK API level. +# include // NOLINT +#endif + +// Defines this to true iff Google Test can use POSIX regular expressions. +#ifndef GTEST_HAS_POSIX_RE +# if GTEST_OS_LINUX_ANDROID +// On Android, is only available starting with Gingerbread. +# define GTEST_HAS_POSIX_RE (__ANDROID_API__ >= 9) +# else +# define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS) +# endif +#endif + +#if GTEST_HAS_POSIX_RE + +// On some platforms, needs someone to define size_t, and +// won't compile otherwise. We can #include it here as we already +// included , which is guaranteed to define size_t through +// . +# include // NOLINT + +# define GTEST_USES_POSIX_RE 1 + +#elif GTEST_OS_WINDOWS + +// is not available on Windows. Use our own simple regex +// implementation instead. +# define GTEST_USES_SIMPLE_RE 1 + +#else + +// may not be available on this platform. Use our own +// simple regex implementation instead. +# define GTEST_USES_SIMPLE_RE 1 + +#endif // GTEST_HAS_POSIX_RE + +#ifndef GTEST_HAS_EXCEPTIONS +// The user didn't tell us whether exceptions are enabled, so we need +// to figure it out. +# if defined(_MSC_VER) || defined(__BORLANDC__) +// MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS +// macro to enable exceptions, so we'll do the same. +// Assumes that exceptions are enabled by default. +# ifndef _HAS_EXCEPTIONS +# define _HAS_EXCEPTIONS 1 +# endif // _HAS_EXCEPTIONS +# define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS +# elif defined(__GNUC__) && __EXCEPTIONS +// gcc defines __EXCEPTIONS to 1 iff exceptions are enabled. +# define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__SUNPRO_CC) +// Sun Pro CC supports exceptions. However, there is no compile-time way of +// detecting whether they are enabled or not. Therefore, we assume that +// they are enabled unless the user tells us otherwise. +# define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__IBMCPP__) && __EXCEPTIONS +// xlC defines __EXCEPTIONS to 1 iff exceptions are enabled. +# define GTEST_HAS_EXCEPTIONS 1 +# elif defined(__HP_aCC) +// Exception handling is in effect by default in HP aCC compiler. It has to +// be turned of by +noeh compiler option if desired. +# define GTEST_HAS_EXCEPTIONS 1 +# else +// For other compilers, we assume exceptions are disabled to be +// conservative. +# define GTEST_HAS_EXCEPTIONS 0 +# endif // defined(_MSC_VER) || defined(__BORLANDC__) +#endif // GTEST_HAS_EXCEPTIONS + +#if !defined(GTEST_HAS_STD_STRING) +// Even though we don't use this macro any longer, we keep it in case +// some clients still depend on it. +# define GTEST_HAS_STD_STRING 1 +#elif !GTEST_HAS_STD_STRING +// The user told us that ::std::string isn't available. +# error "Google Test cannot be used where ::std::string isn't available." +#endif // !defined(GTEST_HAS_STD_STRING) + +#ifndef GTEST_HAS_GLOBAL_STRING +// The user didn't tell us whether ::string is available, so we need +// to figure it out. + +# define GTEST_HAS_GLOBAL_STRING 0 + +#endif // GTEST_HAS_GLOBAL_STRING + +#ifndef GTEST_HAS_STD_WSTRING +// The user didn't tell us whether ::std::wstring is available, so we need +// to figure it out. +// TODO(wan@google.com): uses autoconf to detect whether ::std::wstring +// is available. + +// Cygwin 1.7 and below doesn't support ::std::wstring. +// Solaris' libc++ doesn't support it either. Android has +// no support for it at least as recent as Froyo (2.2). +# define GTEST_HAS_STD_WSTRING \ + (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS)) + +#endif // GTEST_HAS_STD_WSTRING + +#ifndef GTEST_HAS_GLOBAL_WSTRING +// The user didn't tell us whether ::wstring is available, so we need +// to figure it out. +# define GTEST_HAS_GLOBAL_WSTRING \ + (GTEST_HAS_STD_WSTRING && GTEST_HAS_GLOBAL_STRING) +#endif // GTEST_HAS_GLOBAL_WSTRING + +// Determines whether RTTI is available. +#ifndef GTEST_HAS_RTTI +// The user didn't tell us whether RTTI is enabled, so we need to +// figure it out. + +# ifdef _MSC_VER + +# ifdef _CPPRTTI // MSVC defines this macro iff RTTI is enabled. +# define GTEST_HAS_RTTI 1 +# else +# define GTEST_HAS_RTTI 0 +# endif + +// Starting with version 4.3.2, gcc defines __GXX_RTTI iff RTTI is enabled. +# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302) + +# ifdef __GXX_RTTI +// When building against STLport with the Android NDK and with +// -frtti -fno-exceptions, the build fails at link time with undefined +// references to __cxa_bad_typeid. Note sure if STL or toolchain bug, +// so disable RTTI when detected. +# if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR) && \ + !defined(__EXCEPTIONS) +# define GTEST_HAS_RTTI 0 +# else +# define GTEST_HAS_RTTI 1 +# endif // GTEST_OS_LINUX_ANDROID && __STLPORT_MAJOR && !__EXCEPTIONS +# else +# define GTEST_HAS_RTTI 0 +# endif // __GXX_RTTI + +// Clang defines __GXX_RTTI starting with version 3.0, but its manual recommends +// using has_feature instead. has_feature(cxx_rtti) is supported since 2.7, the +// first version with C++ support. +# elif defined(__clang__) + +# define GTEST_HAS_RTTI __has_feature(cxx_rtti) + +// Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if +// both the typeid and dynamic_cast features are present. +# elif defined(__IBMCPP__) && (__IBMCPP__ >= 900) + +# ifdef __RTTI_ALL__ +# define GTEST_HAS_RTTI 1 +# else +# define GTEST_HAS_RTTI 0 +# endif + +# else + +// For all other compilers, we assume RTTI is enabled. +# define GTEST_HAS_RTTI 1 + +# endif // _MSC_VER + +#endif // GTEST_HAS_RTTI + +// It's this header's responsibility to #include when RTTI +// is enabled. +#if GTEST_HAS_RTTI +# include +#endif + +// Determines whether Google Test can use the pthreads library. +#ifndef GTEST_HAS_PTHREAD +// The user didn't tell us explicitly, so we assume pthreads support is +// available on Linux and Mac. +// +// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0 +// to your compiler flags. +# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX \ + || GTEST_OS_QNX) +#endif // GTEST_HAS_PTHREAD + +#if GTEST_HAS_PTHREAD +// gtest-port.h guarantees to #include when GTEST_HAS_PTHREAD is +// true. +# include // NOLINT + +// For timespec and nanosleep, used below. +# include // NOLINT +#endif + +// 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 +# if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR) +// STLport, provided with the Android NDK, has neither or . +# define GTEST_HAS_TR1_TUPLE 0 +# else +// The user didn't tell us not to do it, so we assume it's OK. +# define GTEST_HAS_TR1_TUPLE 1 +# endif +#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. + +// We use our own TR1 tuple if we aren't sure the user has an +// implementation of it already. At this time, libstdc++ 4.0.0+ and +// MSVC 2010 are the only mainstream standard libraries that come +// with a TR1 tuple implementation. NVIDIA's CUDA NVCC compiler +// pretends to be GCC by defining __GNUC__ and friends, but cannot +// compile GCC's tuple implementation. MSVC 2008 (9.0) provides TR1 +// tuple in a 323 MB Feature Pack download, which we cannot assume the +// user has. QNX's QCC compiler is a modified GCC but it doesn't +// support TR1 tuple. libc++ only provides std::tuple, in C++11 mode, +// and it can be used with some compilers that define __GNUC__. +# if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000) \ + && !GTEST_OS_QNX && !defined(_LIBCPP_VERSION)) || _MSC_VER >= 1600 +# define GTEST_ENV_HAS_TR1_TUPLE_ 1 +# endif + +// C++11 specifies that provides std::tuple. Use that if gtest is used +// in C++11 mode and libstdc++ isn't very old (binaries targeting OS X 10.6 +// can build with clang but need to use gcc4.2's libstdc++). +# if GTEST_LANG_CXX11 && (!defined(__GLIBCXX__) || __GLIBCXX__ > 20110325) +# define GTEST_ENV_HAS_STD_TUPLE_ 1 +# endif + +# if GTEST_ENV_HAS_TR1_TUPLE_ || GTEST_ENV_HAS_STD_TUPLE_ +# define GTEST_USE_OWN_TR1_TUPLE 0 +# else +# define GTEST_USE_OWN_TR1_TUPLE 1 +# endif + +#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_USE_OWN_TR1_TUPLE +// This file was GENERATED by command: +// pump.py gtest-tuple.h.pump +// 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_INTERNAL_GTEST_TUPLE_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ + +#include // For ::std::pair. + +// The compiler used in Symbian has a bug that prevents us from declaring the +// tuple template as a friend (it complains that tuple is redefined). This +// hack bypasses the bug by declaring the members that should otherwise be +// private as public. +// Sun Studio versions < 12 also have the above bug. +#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590) +# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public: +#else +# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \ + template friend class tuple; \ + private: +#endif + +// GTEST_n_TUPLE_(T) is the type of an n-tuple. +#define GTEST_0_TUPLE_(T) tuple<> +#define GTEST_1_TUPLE_(T) tuple +#define GTEST_2_TUPLE_(T) tuple +#define GTEST_3_TUPLE_(T) tuple +#define GTEST_4_TUPLE_(T) tuple +#define GTEST_5_TUPLE_(T) tuple +#define GTEST_6_TUPLE_(T) tuple +#define GTEST_7_TUPLE_(T) tuple +#define GTEST_8_TUPLE_(T) tuple +#define GTEST_9_TUPLE_(T) tuple +#define GTEST_10_TUPLE_(T) tuple + +// 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 +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::type is T if T is a reference; otherwise it's const T&. +template +struct ByRef { typedef const T& type; }; // NOLINT +template +struct ByRef { typedef T& type; }; // NOLINT + +// A handy wrapper for ByRef. +#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef::type + +// AddRef::type is T if T is a reference; otherwise it's T&. This +// is the same as tr1::add_reference::type. +template +struct AddRef { typedef T& type; }; // NOLINT +template +struct AddRef { typedef T& type; }; // NOLINT + +// A handy wrapper for AddRef. +#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef::type + +// A helper for implementing get(). +template class Get; + +// A helper for implementing tuple_element. kIndexValid is true +// iff k < the number of fields in tuple type T. +template +struct TupleElement; + +template +struct TupleElement { + typedef T0 type; +}; + +template +struct TupleElement { + typedef T1 type; +}; + +template +struct TupleElement { + typedef T2 type; +}; + +template +struct TupleElement { + typedef T3 type; +}; + +template +struct TupleElement { + typedef T4 type; +}; + +template +struct TupleElement { + typedef T5 type; +}; + +template +struct TupleElement { + typedef T6 type; +}; + +template +struct TupleElement { + typedef T7 type; +}; + +template +struct TupleElement { + typedef T8 type; +}; + +template +struct TupleElement { + typedef T9 type; +}; + +} // namespace gtest_internal + +template <> +class tuple<> { + public: + tuple() {} + tuple(const tuple& /* t */) {} + tuple& operator=(const tuple& /* t */) { return *this; } +}; + +template +class GTEST_1_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_() {} + + explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {} + + tuple(const tuple& t) : f0_(t.f0_) {} + + template + tuple(const GTEST_1_TUPLE_(U)& t) : f0_(t.f0_) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_1_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_1_TUPLE_(U)& t) { + f0_ = t.f0_; + return *this; + } + + T0 f0_; +}; + +template +class GTEST_2_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_() {} + + 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 + tuple(const GTEST_2_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_) {} + template + tuple(const ::std::pair& p) : f0_(p.first), f1_(p.second) {} + + tuple& operator=(const tuple& t) { return CopyFrom(t); } + + template + tuple& operator=(const GTEST_2_TUPLE_(U)& t) { + return CopyFrom(t); + } + template + tuple& operator=(const ::std::pair& p) { + f0_ = p.first; + f1_ = p.second; + return *this; + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + tuple& CopyFrom(const GTEST_2_TUPLE_(U)& t) { + f0_ = t.f0_; + f1_ = t.f1_; + return *this; + } + + T0 f0_; + T1 f1_; +}; + +template +class GTEST_3_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_() {} + + 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 + 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 + tuple& operator=(const GTEST_3_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + 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 +class GTEST_4_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_() {} + + 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 + 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 + tuple& operator=(const GTEST_4_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + 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 +class GTEST_5_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_() {} + + 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 + 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 + tuple& operator=(const GTEST_5_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + 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 +class GTEST_6_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_() {} + + 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 + 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 + tuple& operator=(const GTEST_6_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + 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 +class GTEST_7_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_() {} + + 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 + 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 + tuple& operator=(const GTEST_7_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + 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 +class GTEST_8_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_() {} + + 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 + 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 + tuple& operator=(const GTEST_8_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + 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 +class GTEST_9_TUPLE_(T) { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_() {} + + 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 + 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 + tuple& operator=(const GTEST_9_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + 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 +class tuple { + public: + template friend class gtest_internal::Get; + + tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_(), + f9_() {} + + 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 + 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 + tuple& operator=(const GTEST_10_TUPLE_(U)& t) { + return CopyFrom(t); + } + + GTEST_DECLARE_TUPLE_AS_FRIEND_ + + template + 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 to make_tuple(). And we don't +// implement tie(). + +inline tuple<> make_tuple() { return tuple<>(); } + +template +inline GTEST_1_TUPLE_(T) make_tuple(const T0& f0) { + return GTEST_1_TUPLE_(T)(f0); +} + +template +inline GTEST_2_TUPLE_(T) make_tuple(const T0& f0, const T1& f1) { + return GTEST_2_TUPLE_(T)(f0, f1); +} + +template +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 +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 +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 +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 +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 +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 +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 +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 struct tuple_size; + +template +struct tuple_size { + static const int value = 0; +}; + +template +struct tuple_size { + static const int value = 1; +}; + +template +struct tuple_size { + static const int value = 2; +}; + +template +struct tuple_size { + static const int value = 3; +}; + +template +struct tuple_size { + static const int value = 4; +}; + +template +struct tuple_size { + static const int value = 5; +}; + +template +struct tuple_size { + static const int value = 6; +}; + +template +struct tuple_size { + static const int value = 7; +}; + +template +struct tuple_size { + static const int value = 8; +}; + +template +struct tuple_size { + static const int value = 9; +}; + +template +struct tuple_size { + static const int value = 10; +}; + +template +struct tuple_element { + typedef typename gtest_internal::TupleElement< + k < (tuple_size::value), k, Tuple>::type type; +}; + +#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element::type + +// 6.1.3.4 Element access. + +namespace gtest_internal { + +template <> +class Get<0> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple)) + Field(Tuple& t) { return t.f0_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple)) + ConstField(const Tuple& t) { return t.f0_; } +}; + +template <> +class Get<1> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple)) + Field(Tuple& t) { return t.f1_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple)) + ConstField(const Tuple& t) { return t.f1_; } +}; + +template <> +class Get<2> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple)) + Field(Tuple& t) { return t.f2_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple)) + ConstField(const Tuple& t) { return t.f2_; } +}; + +template <> +class Get<3> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple)) + Field(Tuple& t) { return t.f3_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple)) + ConstField(const Tuple& t) { return t.f3_; } +}; + +template <> +class Get<4> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple)) + Field(Tuple& t) { return t.f4_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple)) + ConstField(const Tuple& t) { return t.f4_; } +}; + +template <> +class Get<5> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple)) + Field(Tuple& t) { return t.f5_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple)) + ConstField(const Tuple& t) { return t.f5_; } +}; + +template <> +class Get<6> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple)) + Field(Tuple& t) { return t.f6_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple)) + ConstField(const Tuple& t) { return t.f6_; } +}; + +template <> +class Get<7> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple)) + Field(Tuple& t) { return t.f7_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple)) + ConstField(const Tuple& t) { return t.f7_; } +}; + +template <> +class Get<8> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple)) + Field(Tuple& t) { return t.f8_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple)) + ConstField(const Tuple& t) { return t.f8_; } +}; + +template <> +class Get<9> { + public: + template + static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple)) + Field(Tuple& t) { return t.f9_; } // NOLINT + + template + static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple)) + ConstField(const Tuple& t) { return t.f9_; } +}; + +} // namespace gtest_internal + +template +GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T))) +get(GTEST_10_TUPLE_(T)& t) { + return gtest_internal::Get::Field(t); +} + +template +GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T))) +get(const GTEST_10_TUPLE_(T)& t) { + return gtest_internal::Get::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::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 +struct SameSizeTuplePrefixComparator; + +template <> +struct SameSizeTuplePrefixComparator<0, 0> { + template + static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) { + return true; + } +}; + +template +struct SameSizeTuplePrefixComparator { + template + static bool Eq(const Tuple1& t1, const Tuple2& t2) { + return SameSizeTuplePrefixComparator::Eq(t1, t2) && + ::std::tr1::get(t1) == ::std::tr1::get(t2); + } +}; + +} // namespace gtest_internal + +template +inline bool operator==(const GTEST_10_TUPLE_(T)& t, + const GTEST_10_TUPLE_(U)& u) { + return gtest_internal::SameSizeTuplePrefixComparator< + tuple_size::value, + tuple_size::value>::Eq(t, u); +} + +template +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_DECLARE_TUPLE_AS_FRIEND_ +#undef GTEST_BY_REF_ +#undef GTEST_ADD_REF_ +#undef GTEST_TUPLE_ELEMENT_ + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ +# elif GTEST_ENV_HAS_STD_TUPLE_ +# include +// C++11 puts its tuple into the ::std namespace rather than +// ::std::tr1. gtest expects tuple to live in ::std::tr1, so put it there. +// This causes undefined behavior, but supported compilers react in +// the way we intend. +namespace std { +namespace tr1 { +using ::std::get; +using ::std::make_tuple; +using ::std::tuple; +using ::std::tuple_element; +using ::std::tuple_size; +} +} + +# 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 +// work as the copy of STLport distributed with Symbian is incomplete. +// By making sure BOOST_HAS_TR1_TUPLE is undefined, we force Boost to +// use its own tuple implementation. +# ifdef BOOST_HAS_TR1_TUPLE +# undef BOOST_HAS_TR1_TUPLE +# endif // BOOST_HAS_TR1_TUPLE + +// This prevents , which defines +// BOOST_HAS_TR1_TUPLE, from being #included by Boost's . +# define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED +# include + +# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000) +// GCC 4.0+ implements tr1/tuple in the header. This does +// not conform to the TR1 spec, which requires the header to be . + +# if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302 +// Until version 4.3.2, gcc has a bug that causes , +// which is #included by , to not compile when RTTI is +// disabled. _TR1_FUNCTIONAL is the header guard for +// . Hence the following #define is a hack to prevent +// from being included. +# define _TR1_FUNCTIONAL 1 +# include +# undef _TR1_FUNCTIONAL // Allows the user to #include + // if he chooses to. +# else +# include // NOLINT +# endif // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302 + +# else +// If the compiler is not GCC 4.0+, we assume the user is using a +// spec-conforming TR1 implementation. +# include // NOLINT +# endif // GTEST_USE_OWN_TR1_TUPLE + +#endif // GTEST_HAS_TR1_TUPLE + +// Determines whether clone(2) is supported. +// Usually it will only be available on Linux, excluding +// Linux on the Itanium architecture. +// Also see http://linux.die.net/man/2/clone. +#ifndef GTEST_HAS_CLONE +// The user didn't tell us, so we need to figure it out. + +# if GTEST_OS_LINUX && !defined(__ia64__) +# if GTEST_OS_LINUX_ANDROID +// On Android, clone() is only available on ARM starting with Gingerbread. +# if defined(__arm__) && __ANDROID_API__ >= 9 +# define GTEST_HAS_CLONE 1 +# else +# define GTEST_HAS_CLONE 0 +# endif +# else +# define GTEST_HAS_CLONE 1 +# endif +# else +# define GTEST_HAS_CLONE 0 +# endif // GTEST_OS_LINUX && !defined(__ia64__) + +#endif // GTEST_HAS_CLONE + +// Determines whether to support stream redirection. This is used to test +// output correctness and to implement death tests. +#ifndef GTEST_HAS_STREAM_REDIRECTION +// By default, we assume that stream redirection is supported on all +// platforms except known mobile ones. +# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN +# define GTEST_HAS_STREAM_REDIRECTION 0 +# else +# define GTEST_HAS_STREAM_REDIRECTION 1 +# endif // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN +#endif // GTEST_HAS_STREAM_REDIRECTION + +// Determines whether to support death tests. +// Google Test does not support death tests for VC 7.1 and earlier as +// abort() in a VC 7.1 application compiled as GUI in debug config +// pops up a dialog window that cannot be suppressed programmatically. +#if (GTEST_OS_LINUX || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \ + (GTEST_OS_MAC && !GTEST_OS_IOS) || GTEST_OS_IOS_SIMULATOR || \ + (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \ + GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX || \ + GTEST_OS_OPENBSD || GTEST_OS_QNX) +# define GTEST_HAS_DEATH_TEST 1 +# include // NOLINT +#endif + +// We don't support MSVC 7.1 with exceptions disabled now. Therefore +// all the compilers we care about are adequate for supporting +// value-parameterized tests. +#define GTEST_HAS_PARAM_TEST 1 + +// Determines whether to support type-driven tests. + +// Typed tests need and variadic macros, which GCC, VC++ 8.0, +// Sun Pro CC, IBM Visual Age, and HP aCC support. +#if defined(__GNUC__) || (_MSC_VER >= 1400) || defined(__SUNPRO_CC) || \ + defined(__IBMCPP__) || defined(__HP_aCC) +# define GTEST_HAS_TYPED_TEST 1 +# define GTEST_HAS_TYPED_TEST_P 1 +#endif + +// Determines whether to support Combine(). This only makes sense when +// value-parameterized tests are enabled. The implementation doesn't +// work on Sun Studio since it doesn't understand templated conversion +// operators. +#if GTEST_HAS_PARAM_TEST && GTEST_HAS_TR1_TUPLE && !defined(__SUNPRO_CC) +# define GTEST_HAS_COMBINE 1 +#endif + +// Determines whether the system compiler uses UTF-16 for encoding wide strings. +#define GTEST_WIDE_STRING_USES_UTF16_ \ + (GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_SYMBIAN || GTEST_OS_AIX) + +// Determines whether test results can be streamed to a socket. +#if GTEST_OS_LINUX +# define GTEST_CAN_STREAM_RESULTS_ 1 +#endif + +// Defines some utility macros. + +// The GNU compiler emits a warning if nested "if" statements are followed by +// an "else" statement and braces are not used to explicitly disambiguate the +// "else" binding. This leads to problems with code like: +// +// if (gate) +// ASSERT_*(condition) << "Some message"; +// +// The "switch (0) case 0:" idiom is used to suppress this. +#ifdef __INTEL_COMPILER +# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ +#else +# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default: // NOLINT +#endif + +// Use this annotation at the end of a struct/class definition to +// prevent the compiler from optimizing away instances that are never +// used. This is useful when all interesting logic happens inside the +// c'tor and / or d'tor. Example: +// +// struct Foo { +// Foo() { ... } +// } GTEST_ATTRIBUTE_UNUSED_; +// +// Also use it after a variable or parameter declaration to tell the +// compiler the variable/parameter does not have to be used. +#if defined(__GNUC__) && !defined(COMPILER_ICC) +# define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused)) +#else +# define GTEST_ATTRIBUTE_UNUSED_ +#endif + +// A macro to disallow operator= +// This should be used in the private: declarations for a class. +#define GTEST_DISALLOW_ASSIGN_(type)\ + void operator=(type const &) + +// A macro to disallow copy constructor and operator= +// This should be used in the private: declarations for a class. +#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type)\ + type(type const &);\ + GTEST_DISALLOW_ASSIGN_(type) + +// Tell the compiler to warn about unused return values for functions declared +// with this macro. The macro should be used on function declarations +// following the argument list: +// +// Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_; +#if defined(__GNUC__) && (GTEST_GCC_VER_ >= 30400) && !defined(COMPILER_ICC) +# define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result)) +#else +# define GTEST_MUST_USE_RESULT_ +#endif // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC + +// Determine whether the compiler supports Microsoft's Structured Exception +// Handling. This is supported by several Windows compilers but generally +// does not exist on any other system. +#ifndef GTEST_HAS_SEH +// The user didn't tell us, so we need to figure it out. + +# if defined(_MSC_VER) || defined(__BORLANDC__) +// These two compilers are known to support SEH. +# define GTEST_HAS_SEH 1 +# else +// Assume no SEH. +# define GTEST_HAS_SEH 0 +# endif + +#endif // GTEST_HAS_SEH + +#ifdef _MSC_VER + +# if GTEST_LINKED_AS_SHARED_LIBRARY +# define GTEST_API_ __declspec(dllimport) +# elif GTEST_CREATE_SHARED_LIBRARY +# define GTEST_API_ __declspec(dllexport) +# endif + +#endif // _MSC_VER + +#ifndef GTEST_API_ +# define GTEST_API_ +#endif + +#ifdef __GNUC__ +// Ask the compiler to never inline a given function. +# define GTEST_NO_INLINE_ __attribute__((noinline)) +#else +# define GTEST_NO_INLINE_ +#endif + +// _LIBCPP_VERSION is defined by the libc++ library from the LLVM project. +#if defined(__GLIBCXX__) || defined(_LIBCPP_VERSION) +# define GTEST_HAS_CXXABI_H_ 1 +#else +# define GTEST_HAS_CXXABI_H_ 0 +#endif + +namespace testing { + +class Message; + +namespace internal { + +// A secret type that Google Test users don't know about. It has no +// definition on purpose. Therefore it's impossible to create a +// Secret object, which is what we want. +class Secret; + +// The GTEST_COMPILE_ASSERT_ macro can be used to verify that a compile time +// expression is true. For example, you could use it to verify the +// size of a static array: +// +// GTEST_COMPILE_ASSERT_(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES, +// content_type_names_incorrect_size); +// +// or to make sure a struct is smaller than a certain size: +// +// GTEST_COMPILE_ASSERT_(sizeof(foo) < 128, foo_too_large); +// +// The second argument to the macro is the name of the variable. If +// the expression is false, most compilers will issue a warning/error +// containing the name of the variable. + +template +struct CompileAssert { +}; + +#define GTEST_COMPILE_ASSERT_(expr, msg) \ + typedef ::testing::internal::CompileAssert<(static_cast(expr))> \ + msg[static_cast(expr) ? 1 : -1] GTEST_ATTRIBUTE_UNUSED_ + +// Implementation details of GTEST_COMPILE_ASSERT_: +// +// - GTEST_COMPILE_ASSERT_ works by defining an array type that has -1 +// elements (and thus is invalid) when the expression is false. +// +// - The simpler definition +// +// #define GTEST_COMPILE_ASSERT_(expr, msg) typedef char msg[(expr) ? 1 : -1] +// +// does not work, as gcc supports variable-length arrays whose sizes +// are determined at run-time (this is gcc's extension and not part +// of the C++ standard). As a result, gcc fails to reject the +// following code with the simple definition: +// +// int foo; +// GTEST_COMPILE_ASSERT_(foo, msg); // not supposed to compile as foo is +// // not a compile-time constant. +// +// - By using the type CompileAssert<(bool(expr))>, we ensures that +// expr is a compile-time constant. (Template arguments must be +// determined at compile-time.) +// +// - The outter parentheses in CompileAssert<(bool(expr))> are necessary +// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written +// +// CompileAssert +// +// instead, these compilers will refuse to compile +// +// GTEST_COMPILE_ASSERT_(5 > 0, some_message); +// +// (They seem to think the ">" in "5 > 0" marks the end of the +// template argument list.) +// +// - The array size is (bool(expr) ? 1 : -1), instead of simply +// +// ((expr) ? 1 : -1). +// +// This is to avoid running into a bug in MS VC 7.1, which +// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1. + +// StaticAssertTypeEqHelper is used by StaticAssertTypeEq defined in gtest.h. +// +// This template is declared, but intentionally undefined. +template +struct StaticAssertTypeEqHelper; + +template +struct StaticAssertTypeEqHelper {}; + +#if GTEST_HAS_GLOBAL_STRING +typedef ::string string; +#else +typedef ::std::string string; +#endif // GTEST_HAS_GLOBAL_STRING + +#if GTEST_HAS_GLOBAL_WSTRING +typedef ::wstring wstring; +#elif GTEST_HAS_STD_WSTRING +typedef ::std::wstring wstring; +#endif // GTEST_HAS_GLOBAL_WSTRING + +// A helper for suppressing warnings on constant condition. It just +// returns 'condition'. +GTEST_API_ bool IsTrue(bool condition); + +// Defines scoped_ptr. + +// This implementation of scoped_ptr is PARTIAL - it only contains +// enough stuff to satisfy Google Test's need. +template +class scoped_ptr { + public: + typedef T element_type; + + explicit scoped_ptr(T* p = NULL) : ptr_(p) {} + ~scoped_ptr() { reset(); } + + T& operator*() const { return *ptr_; } + T* operator->() const { return ptr_; } + T* get() const { return ptr_; } + + T* release() { + T* const ptr = ptr_; + ptr_ = NULL; + return ptr; + } + + void reset(T* p = NULL) { + if (p != ptr_) { + if (IsTrue(sizeof(T) > 0)) { // Makes sure T is a complete type. + delete ptr_; + } + ptr_ = p; + } + } + + private: + T* ptr_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(scoped_ptr); +}; + +// Defines RE. + +// A simple C++ wrapper for . It uses the POSIX Extended +// Regular Expression syntax. +class GTEST_API_ RE { + public: + // A copy constructor is required by the Standard to initialize object + // references from r-values. + RE(const RE& other) { Init(other.pattern()); } + + // Constructs an RE from a string. + RE(const ::std::string& regex) { Init(regex.c_str()); } // NOLINT + +#if GTEST_HAS_GLOBAL_STRING + + RE(const ::string& regex) { Init(regex.c_str()); } // NOLINT + +#endif // GTEST_HAS_GLOBAL_STRING + + RE(const char* regex) { Init(regex); } // NOLINT + ~RE(); + + // Returns the string representation of the regex. + const char* pattern() const { return pattern_; } + + // FullMatch(str, re) returns true iff regular expression re matches + // the entire str. + // PartialMatch(str, re) returns true iff regular expression re + // matches a substring of str (including str itself). + // + // TODO(wan@google.com): make FullMatch() and PartialMatch() work + // when str contains NUL characters. + static bool FullMatch(const ::std::string& str, const RE& re) { + return FullMatch(str.c_str(), re); + } + static bool PartialMatch(const ::std::string& str, const RE& re) { + return PartialMatch(str.c_str(), re); + } + +#if GTEST_HAS_GLOBAL_STRING + + static bool FullMatch(const ::string& str, const RE& re) { + return FullMatch(str.c_str(), re); + } + static bool PartialMatch(const ::string& str, const RE& re) { + return PartialMatch(str.c_str(), re); + } + +#endif // GTEST_HAS_GLOBAL_STRING + + static bool FullMatch(const char* str, const RE& re); + static bool PartialMatch(const char* str, const RE& re); + + private: + void Init(const char* regex); + + // We use a const char* instead of an std::string, as Google Test used to be + // used where std::string is not available. TODO(wan@google.com): change to + // std::string. + const char* pattern_; + bool is_valid_; + +#if GTEST_USES_POSIX_RE + + regex_t full_regex_; // For FullMatch(). + regex_t partial_regex_; // For PartialMatch(). + +#else // GTEST_USES_SIMPLE_RE + + const char* full_pattern_; // For FullMatch(); + +#endif + + GTEST_DISALLOW_ASSIGN_(RE); +}; + +// Formats a source file path and a line number as they would appear +// in an error message from the compiler used to compile this code. +GTEST_API_ ::std::string FormatFileLocation(const char* file, int line); + +// Formats a file location for compiler-independent XML output. +// Although this function is not platform dependent, we put it next to +// FormatFileLocation in order to contrast the two functions. +GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file, + int line); + +// Defines logging utilities: +// GTEST_LOG_(severity) - logs messages at the specified severity level. The +// message itself is streamed into the macro. +// LogToStderr() - directs all log messages to stderr. +// FlushInfoLog() - flushes informational log messages. + +enum GTestLogSeverity { + GTEST_INFO, + GTEST_WARNING, + GTEST_ERROR, + GTEST_FATAL +}; + +// Formats log entry severity, provides a stream object for streaming the +// log message, and terminates the message with a newline when going out of +// scope. +class GTEST_API_ GTestLog { + public: + GTestLog(GTestLogSeverity severity, const char* file, int line); + + // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. + ~GTestLog(); + + ::std::ostream& GetStream() { return ::std::cerr; } + + private: + const GTestLogSeverity severity_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestLog); +}; + +#define GTEST_LOG_(severity) \ + ::testing::internal::GTestLog(::testing::internal::GTEST_##severity, \ + __FILE__, __LINE__).GetStream() + +inline void LogToStderr() {} +inline void FlushInfoLog() { fflush(NULL); } + +// INTERNAL IMPLEMENTATION - DO NOT USE. +// +// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition +// is not satisfied. +// Synopsys: +// GTEST_CHECK_(boolean_condition); +// or +// GTEST_CHECK_(boolean_condition) << "Additional message"; +// +// This checks the condition and if the condition is not satisfied +// it prints message about the condition violation, including the +// condition itself, plus additional message streamed into it, if any, +// and then it aborts the program. It aborts the program irrespective of +// whether it is built in the debug mode or not. +#define GTEST_CHECK_(condition) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::IsTrue(condition)) \ + ; \ + else \ + GTEST_LOG_(FATAL) << "Condition " #condition " failed. " + +// An all-mode assert to verify that the given POSIX-style function +// call returns 0 (indicating success). Known limitation: this +// doesn't expand to a balanced 'if' statement, so enclose the macro +// in {} if you need to use it as the only statement in an 'if' +// branch. +#define GTEST_CHECK_POSIX_SUCCESS_(posix_call) \ + if (const int gtest_error = (posix_call)) \ + GTEST_LOG_(FATAL) << #posix_call << "failed with error " \ + << gtest_error + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Use ImplicitCast_ as a safe version of static_cast for upcasting in +// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a +// const Foo*). When you use ImplicitCast_, the compiler checks that +// the cast is safe. Such explicit ImplicitCast_s are necessary in +// surprisingly many situations where C++ demands an exact type match +// instead of an argument type convertable to a target type. +// +// The syntax for using ImplicitCast_ is the same as for static_cast: +// +// ImplicitCast_(expr) +// +// ImplicitCast_ would have been part of the C++ standard library, +// but the proposal was submitted too late. It will probably make +// its way into the language in the future. +// +// This relatively ugly name is intentional. It prevents clashes with +// similar functions users may have (e.g., implicit_cast). The internal +// namespace alone is not enough because the function can be found by ADL. +template +inline To ImplicitCast_(To x) { return x; } + +// When you upcast (that is, cast a pointer from type Foo to type +// SuperclassOfFoo), it's fine to use ImplicitCast_<>, since upcasts +// always succeed. When you downcast (that is, cast a pointer from +// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because +// how do you know the pointer is really of type SubclassOfFoo? It +// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus, +// when you downcast, you should use this macro. In debug mode, we +// use dynamic_cast<> to double-check the downcast is legal (we die +// if it's not). In normal mode, we do the efficient static_cast<> +// instead. Thus, it's important to test in debug mode to make sure +// the cast is legal! +// This is the only place in the code we should use dynamic_cast<>. +// In particular, you SHOULDN'T be using dynamic_cast<> in order to +// do RTTI (eg code like this: +// if (dynamic_cast(foo)) HandleASubclass1Object(foo); +// if (dynamic_cast(foo)) HandleASubclass2Object(foo); +// You should design the code some other way not to need this. +// +// This relatively ugly name is intentional. It prevents clashes with +// similar functions users may have (e.g., down_cast). The internal +// namespace alone is not enough because the function can be found by ADL. +template // use like this: DownCast_(foo); +inline To DownCast_(From* f) { // so we only accept pointers + // Ensures that To is a sub-type of From *. This test is here only + // for compile-time type checking, and has no overhead in an + // optimized build at run-time, as it will be optimized away + // completely. + if (false) { + const To to = NULL; + ::testing::internal::ImplicitCast_(to); + } + +#if GTEST_HAS_RTTI + // RTTI: debug mode only! + GTEST_CHECK_(f == NULL || dynamic_cast(f) != NULL); +#endif + return static_cast(f); +} + +// Downcasts the pointer of type Base to Derived. +// Derived must be a subclass of Base. The parameter MUST +// point to a class of type Derived, not any subclass of it. +// When RTTI is available, the function performs a runtime +// check to enforce this. +template +Derived* CheckedDowncastToActualType(Base* base) { +#if GTEST_HAS_RTTI + GTEST_CHECK_(typeid(*base) == typeid(Derived)); + return dynamic_cast(base); // NOLINT +#else + return static_cast(base); // Poor man's downcast. +#endif +} + +#if GTEST_HAS_STREAM_REDIRECTION + +// Defines the stderr capturer: +// CaptureStdout - starts capturing stdout. +// GetCapturedStdout - stops capturing stdout and returns the captured string. +// CaptureStderr - starts capturing stderr. +// GetCapturedStderr - stops capturing stderr and returns the captured string. +// +GTEST_API_ void CaptureStdout(); +GTEST_API_ std::string GetCapturedStdout(); +GTEST_API_ void CaptureStderr(); +GTEST_API_ std::string GetCapturedStderr(); + +#endif // GTEST_HAS_STREAM_REDIRECTION + + +#if GTEST_HAS_DEATH_TEST + +const ::std::vector& GetInjectableArgvs(); +void SetInjectableArgvs(const ::std::vector* + new_argvs); + +// A copy of all command line arguments. Set by InitGoogleTest(). +extern ::std::vector g_argvs; + +#endif // GTEST_HAS_DEATH_TEST + +// Defines synchronization primitives. + +#if GTEST_HAS_PTHREAD + +// Sleeps for (roughly) n milli-seconds. This function is only for +// testing Google Test's own constructs. Don't use it in user tests, +// either directly or indirectly. +inline void SleepMilliseconds(int n) { + const timespec time = { + 0, // 0 seconds. + n * 1000L * 1000L, // And n ms. + }; + nanosleep(&time, NULL); +} + +// Allows a controller thread to pause execution of newly created +// threads until notified. Instances of this class must be created +// and destroyed in the controller thread. +// +// This class is only for testing Google Test's own constructs. Do not +// use it in user tests, either directly or indirectly. +class Notification { + public: + Notification() : notified_(false) { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL)); + } + ~Notification() { + pthread_mutex_destroy(&mutex_); + } + + // Notifies all threads created with this notification to start. Must + // be called from the controller thread. + void Notify() { + pthread_mutex_lock(&mutex_); + notified_ = true; + pthread_mutex_unlock(&mutex_); + } + + // Blocks until the controller thread notifies. Must be called from a test + // thread. + void WaitForNotification() { + for (;;) { + pthread_mutex_lock(&mutex_); + const bool notified = notified_; + pthread_mutex_unlock(&mutex_); + if (notified) + break; + SleepMilliseconds(10); + } + } + + private: + pthread_mutex_t mutex_; + bool notified_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification); +}; + +// As a C-function, ThreadFuncWithCLinkage cannot be templated itself. +// Consequently, it cannot select a correct instantiation of ThreadWithParam +// in order to call its Run(). Introducing ThreadWithParamBase as a +// non-templated base class for ThreadWithParam allows us to bypass this +// problem. +class ThreadWithParamBase { + public: + virtual ~ThreadWithParamBase() {} + virtual void Run() = 0; +}; + +// pthread_create() accepts a pointer to a function type with the C linkage. +// According to the Standard (7.5/1), function types with different linkages +// are different even if they are otherwise identical. Some compilers (for +// example, SunStudio) treat them as different types. Since class methods +// cannot be defined with C-linkage we need to define a free C-function to +// pass into pthread_create(). +extern "C" inline void* ThreadFuncWithCLinkage(void* thread) { + static_cast(thread)->Run(); + return NULL; +} + +// Helper class for testing Google Test's multi-threading constructs. +// To use it, write: +// +// void ThreadFunc(int param) { /* Do things with param */ } +// Notification thread_can_start; +// ... +// // The thread_can_start parameter is optional; you can supply NULL. +// ThreadWithParam thread(&ThreadFunc, 5, &thread_can_start); +// thread_can_start.Notify(); +// +// These classes are only for testing Google Test's own constructs. Do +// not use them in user tests, either directly or indirectly. +template +class ThreadWithParam : public ThreadWithParamBase { + public: + typedef void (*UserThreadFunc)(T); + + ThreadWithParam( + UserThreadFunc func, T param, Notification* thread_can_start) + : func_(func), + param_(param), + thread_can_start_(thread_can_start), + finished_(false) { + ThreadWithParamBase* const base = this; + // The thread can be created only after all fields except thread_ + // have been initialized. + GTEST_CHECK_POSIX_SUCCESS_( + pthread_create(&thread_, 0, &ThreadFuncWithCLinkage, base)); + } + ~ThreadWithParam() { Join(); } + + void Join() { + if (!finished_) { + GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, 0)); + finished_ = true; + } + } + + virtual void Run() { + if (thread_can_start_ != NULL) + thread_can_start_->WaitForNotification(); + func_(param_); + } + + private: + const UserThreadFunc func_; // User-supplied thread function. + const T param_; // User-supplied parameter to the thread function. + // When non-NULL, used to block execution until the controller thread + // notifies. + Notification* const thread_can_start_; + bool finished_; // true iff we know that the thread function has finished. + pthread_t thread_; // The native thread object. + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam); +}; + +// MutexBase and Mutex implement mutex on pthreads-based platforms. They +// are used in conjunction with class MutexLock: +// +// Mutex mutex; +// ... +// MutexLock lock(&mutex); // Acquires the mutex and releases it at the end +// // of the current scope. +// +// MutexBase implements behavior for both statically and dynamically +// allocated mutexes. Do not use MutexBase directly. Instead, write +// the following to define a static mutex: +// +// GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex); +// +// You can forward declare a static mutex like this: +// +// GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex); +// +// To create a dynamic mutex, just define an object of type Mutex. +class MutexBase { + public: + // Acquires this mutex. + void Lock() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_)); + owner_ = pthread_self(); + has_owner_ = true; + } + + // Releases this mutex. + void Unlock() { + // Since the lock is being released the owner_ field should no longer be + // considered valid. We don't protect writing to has_owner_ here, as it's + // the caller's responsibility to ensure that the current thread holds the + // mutex when this is called. + has_owner_ = false; + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_)); + } + + // Does nothing if the current thread holds the mutex. Otherwise, crashes + // with high probability. + void AssertHeld() const { + GTEST_CHECK_(has_owner_ && pthread_equal(owner_, pthread_self())) + << "The current thread is not holding the mutex @" << this; + } + + // A static mutex may be used before main() is entered. It may even + // be used before the dynamic initialization stage. Therefore we + // must be able to initialize a static mutex object at link time. + // This means MutexBase has to be a POD and its member variables + // have to be public. + public: + pthread_mutex_t mutex_; // The underlying pthread mutex. + // has_owner_ indicates whether the owner_ field below contains a valid thread + // ID and is therefore safe to inspect (e.g., to use in pthread_equal()). All + // accesses to the owner_ field should be protected by a check of this field. + // An alternative might be to memset() owner_ to all zeros, but there's no + // guarantee that a zero'd pthread_t is necessarily invalid or even different + // from pthread_self(). + bool has_owner_; + pthread_t owner_; // The thread holding the mutex. +}; + +// Forward-declares a static mutex. +# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ + extern ::testing::internal::MutexBase mutex + +// Defines and statically (i.e. at link time) initializes a static mutex. +// The initialization list here does not explicitly initialize each field, +// instead relying on default initialization for the unspecified fields. In +// particular, the owner_ field (a pthread_t) is not explicitly initialized. +// This allows initialization to work whether pthread_t is a scalar or struct. +// The flag -Wmissing-field-initializers must not be specified for this to work. +# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \ + ::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, false } + +// The Mutex class can only be used for mutexes created at runtime. It +// shares its API with MutexBase otherwise. +class Mutex : public MutexBase { + public: + Mutex() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL)); + has_owner_ = false; + } + ~Mutex() { + GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_)); + } + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex); +}; + +// We cannot name this class MutexLock as the ctor declaration would +// conflict with a macro named MutexLock, which is defined on some +// platforms. Hence the typedef trick below. +class GTestMutexLock { + public: + explicit GTestMutexLock(MutexBase* mutex) + : mutex_(mutex) { mutex_->Lock(); } + + ~GTestMutexLock() { mutex_->Unlock(); } + + private: + MutexBase* const mutex_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock); +}; + +typedef GTestMutexLock MutexLock; + +// Helpers for ThreadLocal. + +// pthread_key_create() requires DeleteThreadLocalValue() to have +// C-linkage. Therefore it cannot be templatized to access +// ThreadLocal. Hence the need for class +// ThreadLocalValueHolderBase. +class ThreadLocalValueHolderBase { + public: + virtual ~ThreadLocalValueHolderBase() {} +}; + +// Called by pthread to delete thread-local data stored by +// pthread_setspecific(). +extern "C" inline void DeleteThreadLocalValue(void* value_holder) { + delete static_cast(value_holder); +} + +// Implements thread-local storage on pthreads-based systems. +// +// // Thread 1 +// ThreadLocal tl(100); // 100 is the default value for each thread. +// +// // Thread 2 +// tl.set(150); // Changes the value for thread 2 only. +// EXPECT_EQ(150, tl.get()); +// +// // Thread 1 +// EXPECT_EQ(100, tl.get()); // In thread 1, tl has the original value. +// tl.set(200); +// EXPECT_EQ(200, tl.get()); +// +// The template type argument T must have a public copy constructor. +// In addition, the default ThreadLocal constructor requires T to have +// a public default constructor. +// +// An object managed for a thread by a ThreadLocal instance is deleted +// when the thread exits. Or, if the ThreadLocal instance dies in +// that thread, when the ThreadLocal dies. It's the user's +// responsibility to ensure that all other threads using a ThreadLocal +// have exited when it dies, or the per-thread objects for those +// threads will not be deleted. +// +// Google Test only uses global ThreadLocal objects. That means they +// will die after main() has returned. Therefore, no per-thread +// object managed by Google Test will be leaked as long as all threads +// using Google Test have exited when main() returns. +template +class ThreadLocal { + public: + ThreadLocal() : key_(CreateKey()), + default_() {} + explicit ThreadLocal(const T& value) : key_(CreateKey()), + default_(value) {} + + ~ThreadLocal() { + // Destroys the managed object for the current thread, if any. + DeleteThreadLocalValue(pthread_getspecific(key_)); + + // Releases resources associated with the key. This will *not* + // delete managed objects for other threads. + GTEST_CHECK_POSIX_SUCCESS_(pthread_key_delete(key_)); + } + + T* pointer() { return GetOrCreateValue(); } + const T* pointer() const { return GetOrCreateValue(); } + const T& get() const { return *pointer(); } + void set(const T& value) { *pointer() = value; } + + private: + // Holds a value of type T. + class ValueHolder : public ThreadLocalValueHolderBase { + public: + explicit ValueHolder(const T& value) : value_(value) {} + + T* pointer() { return &value_; } + + private: + T value_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder); + }; + + static pthread_key_t CreateKey() { + pthread_key_t key; + // When a thread exits, DeleteThreadLocalValue() will be called on + // the object managed for that thread. + GTEST_CHECK_POSIX_SUCCESS_( + pthread_key_create(&key, &DeleteThreadLocalValue)); + return key; + } + + T* GetOrCreateValue() const { + ThreadLocalValueHolderBase* const holder = + static_cast(pthread_getspecific(key_)); + if (holder != NULL) { + return CheckedDowncastToActualType(holder)->pointer(); + } + + ValueHolder* const new_holder = new ValueHolder(default_); + ThreadLocalValueHolderBase* const holder_base = new_holder; + GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, holder_base)); + return new_holder->pointer(); + } + + // A key pthreads uses for looking up per-thread values. + const pthread_key_t key_; + const T default_; // The default value for each thread. + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal); +}; + +# define GTEST_IS_THREADSAFE 1 + +#else // GTEST_HAS_PTHREAD + +// A dummy implementation of synchronization primitives (mutex, lock, +// and thread-local variable). Necessary for compiling Google Test where +// mutex is not supported - using Google Test in multiple threads is not +// supported on such platforms. + +class Mutex { + public: + Mutex() {} + void Lock() {} + void Unlock() {} + void AssertHeld() const {} +}; + +# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ + extern ::testing::internal::Mutex mutex + +# define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex + +class GTestMutexLock { + public: + explicit GTestMutexLock(Mutex*) {} // NOLINT +}; + +typedef GTestMutexLock MutexLock; + +template +class ThreadLocal { + public: + ThreadLocal() : value_() {} + explicit ThreadLocal(const T& value) : value_(value) {} + T* pointer() { return &value_; } + const T* pointer() const { return &value_; } + const T& get() const { return value_; } + void set(const T& value) { value_ = value; } + private: + T value_; +}; + +// The above synchronization primitives have dummy implementations. +// Therefore Google Test is not thread-safe. +# define GTEST_IS_THREADSAFE 0 + +#endif // GTEST_HAS_PTHREAD + +// Returns the number of threads running in the process, or 0 to indicate that +// we cannot detect it. +GTEST_API_ size_t GetThreadCount(); + +// Passing non-POD classes through ellipsis (...) crashes the ARM +// compiler and generates a warning in Sun Studio. The Nokia Symbian +// and the IBM XL C/C++ compiler try to instantiate a copy constructor +// for objects passed through ellipsis (...), failing for uncopyable +// objects. We define this to ensure that only POD is passed through +// ellipsis on these systems. +#if defined(__SYMBIAN32__) || defined(__IBMCPP__) || defined(__SUNPRO_CC) +// We lose support for NULL detection where the compiler doesn't like +// passing non-POD classes through ellipsis (...). +# define GTEST_ELLIPSIS_NEEDS_POD_ 1 +#else +# define GTEST_CAN_COMPARE_NULL 1 +#endif + +// The Nokia Symbian and IBM XL C/C++ compilers cannot decide between +// const T& and const T* in a function template. These compilers +// _can_ decide between class template specializations for T and T*, +// so a tr1::type_traits-like is_pointer works. +#if defined(__SYMBIAN32__) || defined(__IBMCPP__) +# define GTEST_NEEDS_IS_POINTER_ 1 +#endif + +template +struct bool_constant { + typedef bool_constant type; + static const bool value = bool_value; +}; +template const bool bool_constant::value; + +typedef bool_constant false_type; +typedef bool_constant true_type; + +template +struct is_pointer : public false_type {}; + +template +struct is_pointer : public true_type {}; + +template +struct IteratorTraits { + typedef typename Iterator::value_type value_type; +}; + +template +struct IteratorTraits { + typedef T value_type; +}; + +template +struct IteratorTraits { + typedef T value_type; +}; + +#if GTEST_OS_WINDOWS +# define GTEST_PATH_SEP_ "\\" +# define GTEST_HAS_ALT_PATH_SEP_ 1 +// The biggest signed integer type the compiler supports. +typedef __int64 BiggestInt; +#else +# define GTEST_PATH_SEP_ "/" +# define GTEST_HAS_ALT_PATH_SEP_ 0 +typedef long long BiggestInt; // NOLINT +#endif // GTEST_OS_WINDOWS + +// Utilities for char. + +// isspace(int ch) and friends accept an unsigned char or EOF. char +// may be signed, depending on the compiler (or compiler flags). +// Therefore we need to cast a char to unsigned char before calling +// isspace(), etc. + +inline bool IsAlpha(char ch) { + return isalpha(static_cast(ch)) != 0; +} +inline bool IsAlNum(char ch) { + return isalnum(static_cast(ch)) != 0; +} +inline bool IsDigit(char ch) { + return isdigit(static_cast(ch)) != 0; +} +inline bool IsLower(char ch) { + return islower(static_cast(ch)) != 0; +} +inline bool IsSpace(char ch) { + return isspace(static_cast(ch)) != 0; +} +inline bool IsUpper(char ch) { + return isupper(static_cast(ch)) != 0; +} +inline bool IsXDigit(char ch) { + return isxdigit(static_cast(ch)) != 0; +} +inline bool IsXDigit(wchar_t ch) { + const unsigned char low_byte = static_cast(ch); + return ch == low_byte && isxdigit(low_byte) != 0; +} + +inline char ToLower(char ch) { + return static_cast(tolower(static_cast(ch))); +} +inline char ToUpper(char ch) { + return static_cast(toupper(static_cast(ch))); +} + +// The testing::internal::posix namespace holds wrappers for common +// POSIX functions. These wrappers hide the differences between +// Windows/MSVC and POSIX systems. Since some compilers define these +// standard functions as macros, the wrapper cannot have the same name +// as the wrapped function. + +namespace posix { + +// Functions with a different name on Windows. + +#if GTEST_OS_WINDOWS + +typedef struct _stat StatStruct; + +# ifdef __BORLANDC__ +inline int IsATTY(int fd) { return isatty(fd); } +inline int StrCaseCmp(const char* s1, const char* s2) { + return stricmp(s1, s2); +} +inline char* StrDup(const char* src) { return strdup(src); } +# else // !__BORLANDC__ +# if GTEST_OS_WINDOWS_MOBILE +inline int IsATTY(int /* fd */) { return 0; } +# else +inline int IsATTY(int fd) { return _isatty(fd); } +# endif // GTEST_OS_WINDOWS_MOBILE +inline int StrCaseCmp(const char* s1, const char* s2) { + return _stricmp(s1, s2); +} +inline char* StrDup(const char* src) { return _strdup(src); } +# endif // __BORLANDC__ + +# if GTEST_OS_WINDOWS_MOBILE +inline int FileNo(FILE* file) { return reinterpret_cast(_fileno(file)); } +// Stat(), RmDir(), and IsDir() are not needed on Windows CE at this +// time and thus not defined there. +# else +inline int FileNo(FILE* file) { return _fileno(file); } +inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); } +inline int RmDir(const char* dir) { return _rmdir(dir); } +inline bool IsDir(const StatStruct& st) { + return (_S_IFDIR & st.st_mode) != 0; +} +# endif // GTEST_OS_WINDOWS_MOBILE + +#else + +typedef struct stat StatStruct; + +inline int FileNo(FILE* file) { return fileno(file); } +inline int IsATTY(int fd) { return isatty(fd); } +inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); } +inline int StrCaseCmp(const char* s1, const char* s2) { + return strcasecmp(s1, s2); +} +inline char* StrDup(const char* src) { return strdup(src); } +inline int RmDir(const char* dir) { return rmdir(dir); } +inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); } + +#endif // GTEST_OS_WINDOWS + +// Functions deprecated by MSVC 8.0. + +#ifdef _MSC_VER +// Temporarily disable warning 4996 (deprecated function). +# pragma warning(push) +# pragma warning(disable:4996) +#endif + +inline const char* StrNCpy(char* dest, const char* src, size_t n) { + return strncpy(dest, src, n); +} + +// ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and +// StrError() aren't needed on Windows CE at this time and thus not +// defined there. + +#if !GTEST_OS_WINDOWS_MOBILE +inline int ChDir(const char* dir) { return chdir(dir); } +#endif +inline FILE* FOpen(const char* path, const char* mode) { + return fopen(path, mode); +} +#if !GTEST_OS_WINDOWS_MOBILE +inline FILE *FReopen(const char* path, const char* mode, FILE* stream) { + return freopen(path, mode, stream); +} +inline FILE* FDOpen(int fd, const char* mode) { return fdopen(fd, mode); } +#endif +inline int FClose(FILE* fp) { return fclose(fp); } +#if !GTEST_OS_WINDOWS_MOBILE +inline int Read(int fd, void* buf, unsigned int count) { + return static_cast(read(fd, buf, count)); +} +inline int Write(int fd, const void* buf, unsigned int count) { + return static_cast(write(fd, buf, count)); +} +inline int Close(int fd) { return close(fd); } +inline const char* StrError(int errnum) { return strerror(errnum); } +#endif +inline const char* GetEnv(const char* name) { +#if GTEST_OS_WINDOWS_MOBILE + // We are on Windows CE, which has no environment variables. + return NULL; +#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9) + // Environment variables which we programmatically clear will be set to the + // empty string rather than unset (NULL). Handle that case. + const char* const env = getenv(name); + return (env != NULL && env[0] != '\0') ? env : NULL; +#else + return getenv(name); +#endif +} + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif + +#if GTEST_OS_WINDOWS_MOBILE +// Windows CE has no C library. The abort() function is used in +// several places in Google Test. This implementation provides a reasonable +// imitation of standard behaviour. +void Abort(); +#else +inline void Abort() { abort(); } +#endif // GTEST_OS_WINDOWS_MOBILE + +} // namespace posix + +// MSVC "deprecates" snprintf and issues warnings wherever it is used. In +// order to avoid these warnings, we need to use _snprintf or _snprintf_s on +// MSVC-based platforms. We map the GTEST_SNPRINTF_ macro to the appropriate +// function in order to achieve that. We use macro definition here because +// snprintf is a variadic function. +#if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE +// MSVC 2005 and above support variadic macros. +# define GTEST_SNPRINTF_(buffer, size, format, ...) \ + _snprintf_s(buffer, size, size, format, __VA_ARGS__) +#elif defined(_MSC_VER) +// Windows CE does not define _snprintf_s and MSVC prior to 2005 doesn't +// complain about _snprintf. +# define GTEST_SNPRINTF_ _snprintf +#else +# define GTEST_SNPRINTF_ snprintf +#endif + +// The maximum number a BiggestInt can represent. This definition +// works no matter BiggestInt is represented in one's complement or +// two's complement. +// +// We cannot rely on numeric_limits in STL, as __int64 and long long +// are not part of standard C++ and numeric_limits doesn't need to be +// defined for them. +const BiggestInt kMaxBiggestInt = + ~(static_cast(1) << (8*sizeof(BiggestInt) - 1)); + +// This template class serves as a compile-time function from size to +// type. It maps a size in bytes to a primitive type with that +// size. e.g. +// +// TypeWithSize<4>::UInt +// +// is typedef-ed to be unsigned int (unsigned integer made up of 4 +// bytes). +// +// Such functionality should belong to STL, but I cannot find it +// there. +// +// Google Test uses this class in the implementation of floating-point +// comparison. +// +// For now it only handles UInt (unsigned int) as that's all Google Test +// needs. Other types can be easily added in the future if need +// arises. +template +class TypeWithSize { + public: + // This prevents the user from using TypeWithSize with incorrect + // values of N. + typedef void UInt; +}; + +// The specialization for size 4. +template <> +class TypeWithSize<4> { + public: + // unsigned int has size 4 in both gcc and MSVC. + // + // As base/basictypes.h doesn't compile on Windows, we cannot use + // uint32, uint64, and etc here. + typedef int Int; + typedef unsigned int UInt; +}; + +// The specialization for size 8. +template <> +class TypeWithSize<8> { + public: +#if GTEST_OS_WINDOWS + typedef __int64 Int; + typedef unsigned __int64 UInt; +#else + typedef long long Int; // NOLINT + typedef unsigned long long UInt; // NOLINT +#endif // GTEST_OS_WINDOWS +}; + +// Integer types of known sizes. +typedef TypeWithSize<4>::Int Int32; +typedef TypeWithSize<4>::UInt UInt32; +typedef TypeWithSize<8>::Int Int64; +typedef TypeWithSize<8>::UInt UInt64; +typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds. + +// Utilities for command line flags and environment variables. + +// Macro for referencing flags. +#define GTEST_FLAG(name) FLAGS_gtest_##name + +// Macros for declaring flags. +#define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name) +#define GTEST_DECLARE_int32_(name) \ + GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name) +#define GTEST_DECLARE_string_(name) \ + GTEST_API_ extern ::std::string GTEST_FLAG(name) + +// Macros for defining flags. +#define GTEST_DEFINE_bool_(name, default_val, doc) \ + GTEST_API_ bool GTEST_FLAG(name) = (default_val) +#define GTEST_DEFINE_int32_(name, default_val, doc) \ + GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val) +#define GTEST_DEFINE_string_(name, default_val, doc) \ + GTEST_API_ ::std::string GTEST_FLAG(name) = (default_val) + +// Thread annotations +#define GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks) +#define GTEST_LOCK_EXCLUDED_(locks) + +// Parses 'str' for a 32-bit signed integer. If successful, writes the result +// to *value and returns true; otherwise leaves *value unchanged and returns +// false. +// TODO(chandlerc): Find a better way to refactor flag and environment parsing +// out of both gtest-port.cc and gtest.cc to avoid exporting this utility +// function. +bool ParseInt32(const Message& src_text, const char* str, Int32* value); + +// Parses a bool/Int32/string from the environment variable +// corresponding to the given Google Test flag. +bool BoolFromGTestEnv(const char* flag, bool default_val); +GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val); +const char* StringFromGTestEnv(const char* flag, const char* default_val); + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ + +#if GTEST_OS_LINUX +# include +# include +# include +# include +#endif // GTEST_OS_LINUX + +#if GTEST_HAS_EXCEPTIONS +# include +#endif + +#include +#include +#include +#include +#include +#include + +// 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 +// 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) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines the Message class. +// +// IMPORTANT NOTE: Due to limitation of the C++ language, we have to +// leave some internal implementation details in this header file. +// They are clearly marked by comments like this: +// +// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +// +// Such code is NOT meant to be used by a user directly, and is subject +// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user +// program! + +#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ +#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ + +#include + + +// Ensures that there is at least one operator<< in the global namespace. +// See Message& operator<<(...) below for why. +void operator<<(const testing::internal::Secret&, int); + +namespace testing { + +// The Message class works like an ostream repeater. +// +// Typical usage: +// +// 1. You stream a bunch of values to a Message object. +// It will remember the text in a stringstream. +// 2. Then you stream the Message object to an ostream. +// This causes the text in the Message to be streamed +// to the ostream. +// +// For example; +// +// testing::Message foo; +// foo << 1 << " != " << 2; +// std::cout << foo; +// +// will print "1 != 2". +// +// Message is not intended to be inherited from. In particular, its +// destructor is not virtual. +// +// Note that stringstream behaves differently in gcc and in MSVC. You +// can stream a NULL char pointer to it in the former, but not in the +// latter (it causes an access violation if you do). The Message +// class hides this difference by treating a NULL char pointer as +// "(null)". +class GTEST_API_ Message { + private: + // The type of basic IO manipulators (endl, ends, and flush) for + // narrow streams. + typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&); + + public: + // Constructs an empty Message. + Message(); + + // Copy constructor. + Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT + *ss_ << msg.GetString(); + } + + // Constructs a Message from a C-string. + explicit Message(const char* str) : ss_(new ::std::stringstream) { + *ss_ << str; + } + +#if GTEST_OS_SYMBIAN + // Streams a value (either a pointer or not) to this object. + template + inline Message& operator <<(const T& value) { + StreamHelper(typename internal::is_pointer::type(), value); + return *this; + } +#else + // Streams a non-pointer value to this object. + template + inline Message& operator <<(const T& val) { + // Some libraries overload << for STL containers. These + // overloads are defined in the global namespace instead of ::std. + // + // C++'s symbol lookup rule (i.e. Koenig lookup) says that these + // overloads are visible in either the std namespace or the global + // namespace, but not other namespaces, including the testing + // namespace which Google Test's Message class is in. + // + // To allow STL containers (and other types that has a << operator + // defined in the global namespace) to be used in Google Test + // assertions, testing::Message must access the custom << operator + // from the global namespace. With this using declaration, + // overloads of << defined in the global namespace and those + // visible via Koenig lookup are both exposed in this function. + using ::operator <<; + *ss_ << val; + return *this; + } + + // Streams a pointer value to this object. + // + // This function is an overload of the previous one. When you + // stream a pointer to a Message, this definition will be used as it + // is more specialized. (The C++ Standard, section + // [temp.func.order].) If you stream a non-pointer, then the + // previous definition will be used. + // + // The reason for this overload is that streaming a NULL pointer to + // ostream is undefined behavior. Depending on the compiler, you + // may get "0", "(nil)", "(null)", or an access violation. To + // ensure consistent result across compilers, we always treat NULL + // as "(null)". + template + inline Message& operator <<(T* const& pointer) { // NOLINT + if (pointer == NULL) { + *ss_ << "(null)"; + } else { + *ss_ << pointer; + } + return *this; + } +#endif // GTEST_OS_SYMBIAN + + // Since the basic IO manipulators are overloaded for both narrow + // and wide streams, we have to provide this specialized definition + // of operator <<, even though its body is the same as the + // templatized version above. Without this definition, streaming + // endl or other basic IO manipulators to Message will confuse the + // compiler. + Message& operator <<(BasicNarrowIoManip val) { + *ss_ << val; + return *this; + } + + // Instead of 1/0, we want to see true/false for bool values. + Message& operator <<(bool b) { + return *this << (b ? "true" : "false"); + } + + // These two overloads allow streaming a wide C string to a Message + // using the UTF-8 encoding. + Message& operator <<(const wchar_t* wide_c_str); + Message& operator <<(wchar_t* wide_c_str); + +#if GTEST_HAS_STD_WSTRING + // Converts the given wide string to a narrow string using the UTF-8 + // encoding, and streams the result to this Message object. + Message& operator <<(const ::std::wstring& wstr); +#endif // GTEST_HAS_STD_WSTRING + +#if GTEST_HAS_GLOBAL_WSTRING + // Converts the given wide string to a narrow string using the UTF-8 + // encoding, and streams the result to this Message object. + Message& operator <<(const ::wstring& wstr); +#endif // GTEST_HAS_GLOBAL_WSTRING + + // Gets the text streamed to this object so far as an std::string. + // Each '\0' character in the buffer is replaced with "\\0". + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + std::string GetString() const; + + private: + +#if GTEST_OS_SYMBIAN + // These are needed as the Nokia Symbian Compiler cannot decide between + // const T& and const T* in a function template. The Nokia compiler _can_ + // decide between class template specializations for T and T*, so a + // tr1::type_traits-like is_pointer works, and we can overload on that. + template + inline void StreamHelper(internal::true_type /*is_pointer*/, T* pointer) { + if (pointer == NULL) { + *ss_ << "(null)"; + } else { + *ss_ << pointer; + } + } + template + inline void StreamHelper(internal::false_type /*is_pointer*/, + const T& value) { + // See the comments in Message& operator <<(const T&) above for why + // we need this using statement. + using ::operator <<; + *ss_ << value; + } +#endif // GTEST_OS_SYMBIAN + + // We'll hold the text streamed to this object here. + const internal::scoped_ptr< ::std::stringstream> ss_; + + // We declare (but don't implement) this to prevent the compiler + // from implementing the assignment operator. + void operator=(const Message&); +}; + +// Streams a Message to an ostream. +inline std::ostream& operator <<(std::ostream& os, const Message& sb) { + return os << sb.GetString(); +} + +namespace internal { + +// Converts a streamable value to an std::string. A NULL pointer is +// converted to "(null)". When the input value is a ::string, +// ::std::string, ::wstring, or ::std::wstring object, each NUL +// character in it is replaced with "\\0". +template +std::string StreamableToString(const T& streamable) { + return (Message() << streamable).GetString(); +} + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ +// 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 +// 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. +// +// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file declares the String class and functions used internally by +// Google Test. They are subject to change without notice. They should not used +// by code external to Google Test. +// +// This header file is #included by . +// It should not be #included by other files. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ + +#ifdef __BORLANDC__ +// string.h is not guaranteed to provide strcpy on C++ Builder. +# include +#endif + +#include +#include + + +namespace testing { +namespace internal { + +// String - an abstract class holding static string utilities. +class GTEST_API_ String { + public: + // Static utility methods + + // Clones a 0-terminated C string, allocating memory using new. The + // caller is responsible for deleting the return value using + // delete[]. Returns the cloned string, or NULL if the input is + // NULL. + // + // This is different from strdup() in string.h, which allocates + // memory using malloc(). + static const char* CloneCString(const char* c_str); + +#if GTEST_OS_WINDOWS_MOBILE + // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be + // able to pass strings to Win32 APIs on CE we need to convert them + // to 'Unicode', UTF-16. + + // Creates a UTF-16 wide string from the given ANSI string, allocating + // memory using new. The caller is responsible for deleting the return + // value using delete[]. Returns the wide string, or NULL if the + // input is NULL. + // + // The wide string is created using the ANSI codepage (CP_ACP) to + // match the behaviour of the ANSI versions of Win32 calls and the + // C runtime. + static LPCWSTR AnsiToUtf16(const char* c_str); + + // Creates an ANSI string from the given wide string, allocating + // memory using new. The caller is responsible for deleting the return + // value using delete[]. Returns the ANSI string, or NULL if the + // input is NULL. + // + // The returned string is created using the ANSI codepage (CP_ACP) to + // match the behaviour of the ANSI versions of Win32 calls and the + // C runtime. + static const char* Utf16ToAnsi(LPCWSTR utf16_str); +#endif + + // Compares two C strings. Returns true iff they have the same content. + // + // Unlike strcmp(), this function can handle NULL argument(s). A + // NULL C string is considered different to any non-NULL C string, + // including the empty string. + static bool CStringEquals(const char* lhs, const char* rhs); + + // Converts a wide C string to a String using the UTF-8 encoding. + // NULL will be converted to "(null)". If an error occurred during + // the conversion, "(failed to convert from wide string)" is + // returned. + static std::string ShowWideCString(const wchar_t* wide_c_str); + + // Compares two wide C strings. Returns true iff they have the same + // content. + // + // Unlike wcscmp(), this function can handle NULL argument(s). A + // NULL C string is considered different to any non-NULL C string, + // including the empty string. + static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs); + + // Compares two C strings, ignoring case. Returns true iff they + // have the same content. + // + // Unlike strcasecmp(), this function can handle NULL argument(s). + // A NULL C string is considered different to any non-NULL C string, + // including the empty string. + static bool CaseInsensitiveCStringEquals(const char* lhs, + const char* rhs); + + // Compares two wide C strings, ignoring case. Returns true iff they + // have the same content. + // + // Unlike wcscasecmp(), this function can handle NULL argument(s). + // A NULL C string is considered different to any non-NULL wide C string, + // including the empty string. + // NB: The implementations on different platforms slightly differ. + // On windows, this method uses _wcsicmp which compares according to LC_CTYPE + // environment variable. On GNU platform this method uses wcscasecmp + // which compares according to LC_CTYPE category of the current locale. + // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the + // current locale. + static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs, + const wchar_t* rhs); + + // Returns true iff the given string ends with the given suffix, ignoring + // case. Any string is considered to end with an empty suffix. + static bool EndsWithCaseInsensitive( + const std::string& str, const std::string& suffix); + + // Formats an int value as "%02d". + static std::string FormatIntWidth2(int value); // "%02d" for width == 2 + + // Formats an int value as "%X". + static std::string FormatHexInt(int value); + + // Formats a byte as "%02X". + static std::string FormatByte(unsigned char value); + + private: + String(); // Not meant to be instantiated. +}; // class String + +// Gets the content of the stringstream's buffer as an std::string. Each '\0' +// character in the buffer is replaced with "\\0". +GTEST_API_ std::string StringStreamToString(::std::stringstream* stream); + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ +// Copyright 2008, 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: keith.ray@gmail.com (Keith Ray) +// +// Google Test filepath utilities +// +// This header file declares classes and functions used internally by +// Google Test. They are subject to change without notice. +// +// This file is #included in . +// Do not include this header file separately! + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ + + +namespace testing { +namespace internal { + +// FilePath - a class for file and directory pathname manipulation which +// handles platform-specific conventions (like the pathname separator). +// Used for helper functions for naming files in a directory for xml output. +// Except for Set methods, all methods are const or static, which provides an +// "immutable value object" -- useful for peace of mind. +// A FilePath with a value ending in a path separator ("like/this/") represents +// a directory, otherwise it is assumed to represent a file. In either case, +// it may or may not represent an actual file or directory in the file system. +// Names are NOT checked for syntax correctness -- no checking for illegal +// characters, malformed paths, etc. + +class GTEST_API_ FilePath { + public: + FilePath() : pathname_("") { } + FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { } + + explicit FilePath(const std::string& pathname) : pathname_(pathname) { + Normalize(); + } + + FilePath& operator=(const FilePath& rhs) { + Set(rhs); + return *this; + } + + void Set(const FilePath& rhs) { + pathname_ = rhs.pathname_; + } + + const std::string& string() const { return pathname_; } + const char* c_str() const { return pathname_.c_str(); } + + // Returns the current working directory, or "" if unsuccessful. + static FilePath GetCurrentDir(); + + // Given directory = "dir", base_name = "test", number = 0, + // extension = "xml", returns "dir/test.xml". If number is greater + // than zero (e.g., 12), returns "dir/test_12.xml". + // On Windows platform, uses \ as the separator rather than /. + static FilePath MakeFileName(const FilePath& directory, + const FilePath& base_name, + int number, + const char* extension); + + // Given directory = "dir", relative_path = "test.xml", + // returns "dir/test.xml". + // On Windows, uses \ as the separator rather than /. + static FilePath ConcatPaths(const FilePath& directory, + const FilePath& relative_path); + + // Returns a pathname for a file that does not currently exist. The pathname + // will be directory/base_name.extension or + // directory/base_name_.extension if directory/base_name.extension + // already exists. The number will be incremented until a pathname is found + // that does not already exist. + // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. + // There could be a race condition if two or more processes are calling this + // function at the same time -- they could both pick the same filename. + static FilePath GenerateUniqueFileName(const FilePath& directory, + const FilePath& base_name, + const char* extension); + + // Returns true iff the path is "". + bool IsEmpty() const { return pathname_.empty(); } + + // If input name has a trailing separator character, removes it and returns + // the name, otherwise return the name string unmodified. + // On Windows platform, uses \ as the separator, other platforms use /. + FilePath RemoveTrailingPathSeparator() const; + + // Returns a copy of the FilePath with the directory part removed. + // Example: FilePath("path/to/file").RemoveDirectoryName() returns + // FilePath("file"). If there is no directory part ("just_a_file"), it returns + // the FilePath unmodified. If there is no file part ("just_a_dir/") it + // returns an empty FilePath (""). + // On Windows platform, '\' is the path separator, otherwise it is '/'. + FilePath RemoveDirectoryName() const; + + // RemoveFileName returns the directory path with the filename removed. + // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". + // If the FilePath is "a_file" or "/a_file", RemoveFileName returns + // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does + // not have a file, like "just/a/dir/", it returns the FilePath unmodified. + // On Windows platform, '\' is the path separator, otherwise it is '/'. + FilePath RemoveFileName() const; + + // Returns a copy of the FilePath with the case-insensitive extension removed. + // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns + // FilePath("dir/file"). If a case-insensitive extension is not + // found, returns a copy of the original FilePath. + FilePath RemoveExtension(const char* extension) const; + + // Creates directories so that path exists. Returns true if successful or if + // the directories already exist; returns false if unable to create + // directories for any reason. Will also return false if the FilePath does + // not represent a directory (that is, it doesn't end with a path separator). + bool CreateDirectoriesRecursively() const; + + // Create the directory so that path exists. Returns true if successful or + // if the directory already exists; returns false if unable to create the + // directory for any reason, including if the parent directory does not + // exist. Not named "CreateDirectory" because that's a macro on Windows. + bool CreateFolder() const; + + // Returns true if FilePath describes something in the file-system, + // either a file, directory, or whatever, and that something exists. + bool FileOrDirectoryExists() const; + + // Returns true if pathname describes a directory in the file-system + // that exists. + bool DirectoryExists() const; + + // Returns true if FilePath ends with a path separator, which indicates that + // it is intended to represent a directory. Returns false otherwise. + // This does NOT check that a directory (or file) actually exists. + bool IsDirectory() const; + + // Returns true if pathname describes a root directory. (Windows has one + // root directory per disk drive.) + bool IsRootDirectory() const; + + // Returns true if pathname describes an absolute path. + bool IsAbsolutePath() const; + + private: + // Replaces multiple consecutive separators with a single separator. + // For example, "bar///foo" becomes "bar/foo". Does not eliminate other + // redundancies that might be in a pathname involving "." or "..". + // + // A pathname with multiple consecutive separators may occur either through + // user error or as a result of some scripts or APIs that generate a pathname + // with a trailing separator. On other platforms the same API or script + // may NOT generate a pathname with a trailing "/". Then elsewhere that + // pathname may have another "/" and pathname components added to it, + // without checking for the separator already being there. + // The script language and operating system may allow paths like "foo//bar" + // but some of the functions in FilePath will not handle that correctly. In + // particular, RemoveTrailingPathSeparator() only removes one separator, and + // it is called in CreateDirectoriesRecursively() assuming that it will change + // a pathname from directory syntax (trailing separator) to filename syntax. + // + // On Windows this method also replaces the alternate path separator '/' with + // the primary path separator '\\', so that for example "bar\\/\\foo" becomes + // "bar\\foo". + + void Normalize(); + + // Returns a pointer to the last occurence of a valid path separator in + // the FilePath. On Windows, for example, both '/' and '\' are valid path + // separators. Returns NULL if no path separator was found. + const char* FindLastPathSeparator() const; + + std::string pathname_; +}; // class FilePath + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ +// This file was GENERATED by command: +// pump.py gtest-type-util.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2008 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) + +// Type utilities needed for implementing typed and type-parameterized +// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND! +// +// Currently we support at most 50 types in a list, and at most 50 +// type-parameterized tests in one type-parameterized test case. +// Please contact googletestframework@googlegroups.com if you need +// more. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ + + +// #ifdef __GNUC__ is too general here. It is possible to use gcc without using +// libstdc++ (which is where cxxabi.h comes from). +# if GTEST_HAS_CXXABI_H_ +# include +# elif defined(__HP_aCC) +# include +# endif // GTEST_HASH_CXXABI_H_ + +namespace testing { +namespace internal { + +// GetTypeName() returns a human-readable name of type T. +// NB: This function is also used in Google Mock, so don't move it inside of +// the typed-test-only section below. +template +std::string GetTypeName() { +# if GTEST_HAS_RTTI + + const char* const name = typeid(T).name(); +# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC) + int status = 0; + // gcc's implementation of typeid(T).name() mangles the type name, + // so we have to demangle it. +# if GTEST_HAS_CXXABI_H_ + using abi::__cxa_demangle; +# endif // GTEST_HAS_CXXABI_H_ + char* const readable_name = __cxa_demangle(name, 0, 0, &status); + const std::string name_str(status == 0 ? readable_name : name); + free(readable_name); + return name_str; +# else + return name; +# endif // GTEST_HAS_CXXABI_H_ || __HP_aCC + +# else + + return ""; + +# endif // GTEST_HAS_RTTI +} + +#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +// AssertyTypeEq::type is defined iff T1 and T2 are the same +// type. This can be used as a compile-time assertion to ensure that +// two types are equal. + +template +struct AssertTypeEq; + +template +struct AssertTypeEq { + typedef bool type; +}; + +// A unique type used as the default value for the arguments of class +// template Types. This allows us to simulate variadic templates +// (e.g. Types, Type, and etc), which C++ doesn't +// support directly. +struct None {}; + +// The following family of struct and struct templates are used to +// represent type lists. In particular, TypesN +// represents a type list with N types (T1, T2, ..., and TN) in it. +// Except for Types0, every struct in the family has two member types: +// Head for the first type in the list, and Tail for the rest of the +// list. + +// The empty type list. +struct Types0 {}; + +// Type lists of length 1, 2, 3, and so on. + +template +struct Types1 { + typedef T1 Head; + typedef Types0 Tail; +}; +template +struct Types2 { + typedef T1 Head; + typedef Types1 Tail; +}; + +template +struct Types3 { + typedef T1 Head; + typedef Types2 Tail; +}; + +template +struct Types4 { + typedef T1 Head; + typedef Types3 Tail; +}; + +template +struct Types5 { + typedef T1 Head; + typedef Types4 Tail; +}; + +template +struct Types6 { + typedef T1 Head; + typedef Types5 Tail; +}; + +template +struct Types7 { + typedef T1 Head; + typedef Types6 Tail; +}; + +template +struct Types8 { + typedef T1 Head; + typedef Types7 Tail; +}; + +template +struct Types9 { + typedef T1 Head; + typedef Types8 Tail; +}; + +template +struct Types10 { + typedef T1 Head; + typedef Types9 Tail; +}; + +template +struct Types11 { + typedef T1 Head; + typedef Types10 Tail; +}; + +template +struct Types12 { + typedef T1 Head; + typedef Types11 Tail; +}; + +template +struct Types13 { + typedef T1 Head; + typedef Types12 Tail; +}; + +template +struct Types14 { + typedef T1 Head; + typedef Types13 Tail; +}; + +template +struct Types15 { + typedef T1 Head; + typedef Types14 Tail; +}; + +template +struct Types16 { + typedef T1 Head; + typedef Types15 Tail; +}; + +template +struct Types17 { + typedef T1 Head; + typedef Types16 Tail; +}; + +template +struct Types18 { + typedef T1 Head; + typedef Types17 Tail; +}; + +template +struct Types19 { + typedef T1 Head; + typedef Types18 Tail; +}; + +template +struct Types20 { + typedef T1 Head; + typedef Types19 Tail; +}; + +template +struct Types21 { + typedef T1 Head; + typedef Types20 Tail; +}; + +template +struct Types22 { + typedef T1 Head; + typedef Types21 Tail; +}; + +template +struct Types23 { + typedef T1 Head; + typedef Types22 Tail; +}; + +template +struct Types24 { + typedef T1 Head; + typedef Types23 Tail; +}; + +template +struct Types25 { + typedef T1 Head; + typedef Types24 Tail; +}; + +template +struct Types26 { + typedef T1 Head; + typedef Types25 Tail; +}; + +template +struct Types27 { + typedef T1 Head; + typedef Types26 Tail; +}; + +template +struct Types28 { + typedef T1 Head; + typedef Types27 Tail; +}; + +template +struct Types29 { + typedef T1 Head; + typedef Types28 Tail; +}; + +template +struct Types30 { + typedef T1 Head; + typedef Types29 Tail; +}; + +template +struct Types31 { + typedef T1 Head; + typedef Types30 Tail; +}; + +template +struct Types32 { + typedef T1 Head; + typedef Types31 Tail; +}; + +template +struct Types33 { + typedef T1 Head; + typedef Types32 Tail; +}; + +template +struct Types34 { + typedef T1 Head; + typedef Types33 Tail; +}; + +template +struct Types35 { + typedef T1 Head; + typedef Types34 Tail; +}; + +template +struct Types36 { + typedef T1 Head; + typedef Types35 Tail; +}; + +template +struct Types37 { + typedef T1 Head; + typedef Types36 Tail; +}; + +template +struct Types38 { + typedef T1 Head; + typedef Types37 Tail; +}; + +template +struct Types39 { + typedef T1 Head; + typedef Types38 Tail; +}; + +template +struct Types40 { + typedef T1 Head; + typedef Types39 Tail; +}; + +template +struct Types41 { + typedef T1 Head; + typedef Types40 Tail; +}; + +template +struct Types42 { + typedef T1 Head; + typedef Types41 Tail; +}; + +template +struct Types43 { + typedef T1 Head; + typedef Types42 Tail; +}; + +template +struct Types44 { + typedef T1 Head; + typedef Types43 Tail; +}; + +template +struct Types45 { + typedef T1 Head; + typedef Types44 Tail; +}; + +template +struct Types46 { + typedef T1 Head; + typedef Types45 Tail; +}; + +template +struct Types47 { + typedef T1 Head; + typedef Types46 Tail; +}; + +template +struct Types48 { + typedef T1 Head; + typedef Types47 Tail; +}; + +template +struct Types49 { + typedef T1 Head; + typedef Types48 Tail; +}; + +template +struct Types50 { + typedef T1 Head; + typedef Types49 Tail; +}; + + +} // namespace internal + +// We don't want to require the users to write TypesN<...> directly, +// as that would require them to count the length. Types<...> is much +// easier to write, but generates horrible messages when there is a +// compiler error, as gcc insists on printing out each template +// argument, even if it has the default value (this means Types +// will appear as Types in the compiler +// errors). +// +// Our solution is to combine the best part of the two approaches: a +// user would write Types, and Google Test will translate +// that to TypesN internally to make error messages +// readable. The translation is done by the 'type' member of the +// Types template. +template +struct Types { + typedef internal::Types50 type; +}; + +template <> +struct Types { + typedef internal::Types0 type; +}; +template +struct Types { + typedef internal::Types1 type; +}; +template +struct Types { + typedef internal::Types2 type; +}; +template +struct Types { + typedef internal::Types3 type; +}; +template +struct Types { + typedef internal::Types4 type; +}; +template +struct Types { + typedef internal::Types5 type; +}; +template +struct Types { + typedef internal::Types6 type; +}; +template +struct Types { + typedef internal::Types7 type; +}; +template +struct Types { + typedef internal::Types8 type; +}; +template +struct Types { + typedef internal::Types9 type; +}; +template +struct Types { + typedef internal::Types10 type; +}; +template +struct Types { + typedef internal::Types11 type; +}; +template +struct Types { + typedef internal::Types12 type; +}; +template +struct Types { + typedef internal::Types13 type; +}; +template +struct Types { + typedef internal::Types14 type; +}; +template +struct Types { + typedef internal::Types15 type; +}; +template +struct Types { + typedef internal::Types16 type; +}; +template +struct Types { + typedef internal::Types17 type; +}; +template +struct Types { + typedef internal::Types18 type; +}; +template +struct Types { + typedef internal::Types19 type; +}; +template +struct Types { + typedef internal::Types20 type; +}; +template +struct Types { + typedef internal::Types21 type; +}; +template +struct Types { + typedef internal::Types22 type; +}; +template +struct Types { + typedef internal::Types23 type; +}; +template +struct Types { + typedef internal::Types24 type; +}; +template +struct Types { + typedef internal::Types25 type; +}; +template +struct Types { + typedef internal::Types26 type; +}; +template +struct Types { + typedef internal::Types27 type; +}; +template +struct Types { + typedef internal::Types28 type; +}; +template +struct Types { + typedef internal::Types29 type; +}; +template +struct Types { + typedef internal::Types30 type; +}; +template +struct Types { + typedef internal::Types31 type; +}; +template +struct Types { + typedef internal::Types32 type; +}; +template +struct Types { + typedef internal::Types33 type; +}; +template +struct Types { + typedef internal::Types34 type; +}; +template +struct Types { + typedef internal::Types35 type; +}; +template +struct Types { + typedef internal::Types36 type; +}; +template +struct Types { + typedef internal::Types37 type; +}; +template +struct Types { + typedef internal::Types38 type; +}; +template +struct Types { + typedef internal::Types39 type; +}; +template +struct Types { + typedef internal::Types40 type; +}; +template +struct Types { + typedef internal::Types41 type; +}; +template +struct Types { + typedef internal::Types42 type; +}; +template +struct Types { + typedef internal::Types43 type; +}; +template +struct Types { + typedef internal::Types44 type; +}; +template +struct Types { + typedef internal::Types45 type; +}; +template +struct Types { + typedef internal::Types46 type; +}; +template +struct Types { + typedef internal::Types47 type; +}; +template +struct Types { + typedef internal::Types48 type; +}; +template +struct Types { + typedef internal::Types49 type; +}; + +namespace internal { + +# define GTEST_TEMPLATE_ template class + +// The template "selector" struct TemplateSel is used to +// represent Tmpl, which must be a class template with one type +// parameter, as a type. TemplateSel::Bind::type is defined +// as the type Tmpl. This allows us to actually instantiate the +// template "selected" by TemplateSel. +// +// This trick is necessary for simulating typedef for class templates, +// which C++ doesn't support directly. +template +struct TemplateSel { + template + struct Bind { + typedef Tmpl type; + }; +}; + +# define GTEST_BIND_(TmplSel, T) \ + TmplSel::template Bind::type + +// A unique struct template used as the default value for the +// arguments of class template Templates. This allows us to simulate +// variadic templates (e.g. Templates, Templates, +// and etc), which C++ doesn't support directly. +template +struct NoneT {}; + +// The following family of struct and struct templates are used to +// represent template lists. In particular, TemplatesN represents a list of N templates (T1, T2, ..., and TN). Except +// for Templates0, every struct in the family has two member types: +// Head for the selector of the first template in the list, and Tail +// for the rest of the list. + +// The empty template list. +struct Templates0 {}; + +// Template lists of length 1, 2, 3, and so on. + +template +struct Templates1 { + typedef TemplateSel Head; + typedef Templates0 Tail; +}; +template +struct Templates2 { + typedef TemplateSel Head; + typedef Templates1 Tail; +}; + +template +struct Templates3 { + typedef TemplateSel Head; + typedef Templates2 Tail; +}; + +template +struct Templates4 { + typedef TemplateSel Head; + typedef Templates3 Tail; +}; + +template +struct Templates5 { + typedef TemplateSel Head; + typedef Templates4 Tail; +}; + +template +struct Templates6 { + typedef TemplateSel Head; + typedef Templates5 Tail; +}; + +template +struct Templates7 { + typedef TemplateSel Head; + typedef Templates6 Tail; +}; + +template +struct Templates8 { + typedef TemplateSel Head; + typedef Templates7 Tail; +}; + +template +struct Templates9 { + typedef TemplateSel Head; + typedef Templates8 Tail; +}; + +template +struct Templates10 { + typedef TemplateSel Head; + typedef Templates9 Tail; +}; + +template +struct Templates11 { + typedef TemplateSel Head; + typedef Templates10 Tail; +}; + +template +struct Templates12 { + typedef TemplateSel Head; + typedef Templates11 Tail; +}; + +template +struct Templates13 { + typedef TemplateSel Head; + typedef Templates12 Tail; +}; + +template +struct Templates14 { + typedef TemplateSel Head; + typedef Templates13 Tail; +}; + +template +struct Templates15 { + typedef TemplateSel Head; + typedef Templates14 Tail; +}; + +template +struct Templates16 { + typedef TemplateSel Head; + typedef Templates15 Tail; +}; + +template +struct Templates17 { + typedef TemplateSel Head; + typedef Templates16 Tail; +}; + +template +struct Templates18 { + typedef TemplateSel Head; + typedef Templates17 Tail; +}; + +template +struct Templates19 { + typedef TemplateSel Head; + typedef Templates18 Tail; +}; + +template +struct Templates20 { + typedef TemplateSel Head; + typedef Templates19 Tail; +}; + +template +struct Templates21 { + typedef TemplateSel Head; + typedef Templates20 Tail; +}; + +template +struct Templates22 { + typedef TemplateSel Head; + typedef Templates21 Tail; +}; + +template +struct Templates23 { + typedef TemplateSel Head; + typedef Templates22 Tail; +}; + +template +struct Templates24 { + typedef TemplateSel Head; + typedef Templates23 Tail; +}; + +template +struct Templates25 { + typedef TemplateSel Head; + typedef Templates24 Tail; +}; + +template +struct Templates26 { + typedef TemplateSel Head; + typedef Templates25 Tail; +}; + +template +struct Templates27 { + typedef TemplateSel Head; + typedef Templates26 Tail; +}; + +template +struct Templates28 { + typedef TemplateSel Head; + typedef Templates27 Tail; +}; + +template +struct Templates29 { + typedef TemplateSel Head; + typedef Templates28 Tail; +}; + +template +struct Templates30 { + typedef TemplateSel Head; + typedef Templates29 Tail; +}; + +template +struct Templates31 { + typedef TemplateSel Head; + typedef Templates30 Tail; +}; + +template +struct Templates32 { + typedef TemplateSel Head; + typedef Templates31 Tail; +}; + +template +struct Templates33 { + typedef TemplateSel Head; + typedef Templates32 Tail; +}; + +template +struct Templates34 { + typedef TemplateSel Head; + typedef Templates33 Tail; +}; + +template +struct Templates35 { + typedef TemplateSel Head; + typedef Templates34 Tail; +}; + +template +struct Templates36 { + typedef TemplateSel Head; + typedef Templates35 Tail; +}; + +template +struct Templates37 { + typedef TemplateSel Head; + typedef Templates36 Tail; +}; + +template +struct Templates38 { + typedef TemplateSel Head; + typedef Templates37 Tail; +}; + +template +struct Templates39 { + typedef TemplateSel Head; + typedef Templates38 Tail; +}; + +template +struct Templates40 { + typedef TemplateSel Head; + typedef Templates39 Tail; +}; + +template +struct Templates41 { + typedef TemplateSel Head; + typedef Templates40 Tail; +}; + +template +struct Templates42 { + typedef TemplateSel Head; + typedef Templates41 Tail; +}; + +template +struct Templates43 { + typedef TemplateSel Head; + typedef Templates42 Tail; +}; + +template +struct Templates44 { + typedef TemplateSel Head; + typedef Templates43 Tail; +}; + +template +struct Templates45 { + typedef TemplateSel Head; + typedef Templates44 Tail; +}; + +template +struct Templates46 { + typedef TemplateSel Head; + typedef Templates45 Tail; +}; + +template +struct Templates47 { + typedef TemplateSel Head; + typedef Templates46 Tail; +}; + +template +struct Templates48 { + typedef TemplateSel Head; + typedef Templates47 Tail; +}; + +template +struct Templates49 { + typedef TemplateSel Head; + typedef Templates48 Tail; +}; + +template +struct Templates50 { + typedef TemplateSel Head; + typedef Templates49 Tail; +}; + + +// We don't want to require the users to write TemplatesN<...> directly, +// as that would require them to count the length. Templates<...> is much +// easier to write, but generates horrible messages when there is a +// compiler error, as gcc insists on printing out each template +// argument, even if it has the default value (this means Templates +// will appear as Templates in the compiler +// errors). +// +// Our solution is to combine the best part of the two approaches: a +// user would write Templates, and Google Test will translate +// that to TemplatesN internally to make error messages +// readable. The translation is done by the 'type' member of the +// Templates template. +template +struct Templates { + typedef Templates50 type; +}; + +template <> +struct Templates { + typedef Templates0 type; +}; +template +struct Templates { + typedef Templates1 type; +}; +template +struct Templates { + typedef Templates2 type; +}; +template +struct Templates { + typedef Templates3 type; +}; +template +struct Templates { + typedef Templates4 type; +}; +template +struct Templates { + typedef Templates5 type; +}; +template +struct Templates { + typedef Templates6 type; +}; +template +struct Templates { + typedef Templates7 type; +}; +template +struct Templates { + typedef Templates8 type; +}; +template +struct Templates { + typedef Templates9 type; +}; +template +struct Templates { + typedef Templates10 type; +}; +template +struct Templates { + typedef Templates11 type; +}; +template +struct Templates { + typedef Templates12 type; +}; +template +struct Templates { + typedef Templates13 type; +}; +template +struct Templates { + typedef Templates14 type; +}; +template +struct Templates { + typedef Templates15 type; +}; +template +struct Templates { + typedef Templates16 type; +}; +template +struct Templates { + typedef Templates17 type; +}; +template +struct Templates { + typedef Templates18 type; +}; +template +struct Templates { + typedef Templates19 type; +}; +template +struct Templates { + typedef Templates20 type; +}; +template +struct Templates { + typedef Templates21 type; +}; +template +struct Templates { + typedef Templates22 type; +}; +template +struct Templates { + typedef Templates23 type; +}; +template +struct Templates { + typedef Templates24 type; +}; +template +struct Templates { + typedef Templates25 type; +}; +template +struct Templates { + typedef Templates26 type; +}; +template +struct Templates { + typedef Templates27 type; +}; +template +struct Templates { + typedef Templates28 type; +}; +template +struct Templates { + typedef Templates29 type; +}; +template +struct Templates { + typedef Templates30 type; +}; +template +struct Templates { + typedef Templates31 type; +}; +template +struct Templates { + typedef Templates32 type; +}; +template +struct Templates { + typedef Templates33 type; +}; +template +struct Templates { + typedef Templates34 type; +}; +template +struct Templates { + typedef Templates35 type; +}; +template +struct Templates { + typedef Templates36 type; +}; +template +struct Templates { + typedef Templates37 type; +}; +template +struct Templates { + typedef Templates38 type; +}; +template +struct Templates { + typedef Templates39 type; +}; +template +struct Templates { + typedef Templates40 type; +}; +template +struct Templates { + typedef Templates41 type; +}; +template +struct Templates { + typedef Templates42 type; +}; +template +struct Templates { + typedef Templates43 type; +}; +template +struct Templates { + typedef Templates44 type; +}; +template +struct Templates { + typedef Templates45 type; +}; +template +struct Templates { + typedef Templates46 type; +}; +template +struct Templates { + typedef Templates47 type; +}; +template +struct Templates { + typedef Templates48 type; +}; +template +struct Templates { + typedef Templates49 type; +}; + +// The TypeList template makes it possible to use either a single type +// or a Types<...> list in TYPED_TEST_CASE() and +// INSTANTIATE_TYPED_TEST_CASE_P(). + +template +struct TypeList { + typedef Types1 type; +}; + +template +struct TypeList > { + typedef typename Types::type type; +}; + +#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ + +// Due to C++ preprocessor weirdness, we need double indirection to +// concatenate two tokens when one of them is __LINE__. Writing +// +// foo ## __LINE__ +// +// will result in the token foo__LINE__, instead of foo followed by +// the current line number. For more details, see +// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6 +#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar) +#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar + +class ProtocolMessage; +namespace proto2 { class Message; } + +namespace testing { + +// Forward declarations. + +class AssertionResult; // Result of an assertion. +class Message; // Represents a failure message. +class Test; // Represents a test. +class TestInfo; // Information about a test. +class TestPartResult; // Result of a test part. +class UnitTest; // A collection of test cases. + +template +::std::string PrintToString(const T& value); + +namespace internal { + +struct TraceInfo; // Information about a trace point. +class ScopedTrace; // Implements scoped trace. +class TestInfoImpl; // Opaque implementation of TestInfo +class UnitTestImpl; // Opaque implementation of UnitTest + +// How many times InitGoogleTest() has been called. +GTEST_API_ extern int g_init_gtest_count; + +// The text used in failure messages to indicate the start of the +// stack trace. +GTEST_API_ extern const char kStackTraceMarker[]; + +// Two overloaded helpers for checking at compile time whether an +// expression is a null pointer literal (i.e. NULL or any 0-valued +// compile-time integral constant). Their return values have +// different sizes, so we can use sizeof() to test which version is +// picked by the compiler. These helpers have no implementations, as +// we only need their signatures. +// +// Given IsNullLiteralHelper(x), the compiler will pick the first +// version if x can be implicitly converted to Secret*, and pick the +// second version otherwise. Since Secret is a secret and incomplete +// type, the only expression a user can write that has type Secret* is +// a null pointer literal. Therefore, we know that x is a null +// pointer literal if and only if the first version is picked by the +// compiler. +char IsNullLiteralHelper(Secret* p); +char (&IsNullLiteralHelper(...))[2]; // NOLINT + +// A compile-time bool constant that is true if and only if x is a +// null pointer literal (i.e. NULL or any 0-valued compile-time +// integral constant). +#ifdef GTEST_ELLIPSIS_NEEDS_POD_ +// We lose support for NULL detection where the compiler doesn't like +// passing non-POD classes through ellipsis (...). +# define GTEST_IS_NULL_LITERAL_(x) false +#else +# define GTEST_IS_NULL_LITERAL_(x) \ + (sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1) +#endif // GTEST_ELLIPSIS_NEEDS_POD_ + +// Appends the user-supplied message to the Google-Test-generated message. +GTEST_API_ std::string AppendUserMessage( + const std::string& gtest_msg, const Message& user_msg); + +#if GTEST_HAS_EXCEPTIONS + +// This exception is thrown by (and only by) a failed Google Test +// assertion when GTEST_FLAG(throw_on_failure) is true (if exceptions +// are enabled). We derive it from std::runtime_error, which is for +// errors presumably detectable only at run time. Since +// std::runtime_error inherits from std::exception, many testing +// frameworks know how to extract and print the message inside it. +class GTEST_API_ GoogleTestFailureException : public ::std::runtime_error { + public: + explicit GoogleTestFailureException(const TestPartResult& failure); +}; + +#endif // GTEST_HAS_EXCEPTIONS + +// A helper class for creating scoped traces in user programs. +class GTEST_API_ ScopedTrace { + public: + // The c'tor pushes the given source file location and message onto + // a trace stack maintained by Google Test. + ScopedTrace(const char* file, int line, const Message& message); + + // The d'tor pops the info pushed by the c'tor. + // + // Note that the d'tor is not virtual in order to be efficient. + // Don't inherit from ScopedTrace! + ~ScopedTrace(); + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace); +} GTEST_ATTRIBUTE_UNUSED_; // A ScopedTrace object does its job in its + // c'tor and d'tor. Therefore it doesn't + // need to be used otherwise. + +// Constructs and returns the message for an equality assertion +// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure. +// +// The first four parameters are the expressions used in the assertion +// and their values, as strings. For example, for ASSERT_EQ(foo, bar) +// where foo is 5 and bar is 6, we have: +// +// expected_expression: "foo" +// actual_expression: "bar" +// expected_value: "5" +// actual_value: "6" +// +// The ignoring_case parameter is true iff the assertion is a +// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will +// be inserted into the message. +GTEST_API_ AssertionResult EqFailure(const char* expected_expression, + const char* actual_expression, + const std::string& expected_value, + const std::string& actual_value, + bool ignoring_case); + +// Constructs a failure message for Boolean assertions such as EXPECT_TRUE. +GTEST_API_ std::string GetBoolAssertionFailureMessage( + const AssertionResult& assertion_result, + const char* expression_text, + const char* actual_predicate_value, + const char* expected_predicate_value); + +// This template class represents an IEEE floating-point number +// (either single-precision or double-precision, depending on the +// template parameters). +// +// The purpose of this class is to do more sophisticated number +// comparison. (Due to round-off error, etc, it's very unlikely that +// two floating-points will be equal exactly. Hence a naive +// comparison by the == operation often doesn't work.) +// +// Format of IEEE floating-point: +// +// The most-significant bit being the leftmost, an IEEE +// floating-point looks like +// +// sign_bit exponent_bits fraction_bits +// +// Here, sign_bit is a single bit that designates the sign of the +// number. +// +// For float, there are 8 exponent bits and 23 fraction bits. +// +// For double, there are 11 exponent bits and 52 fraction bits. +// +// More details can be found at +// http://en.wikipedia.org/wiki/IEEE_floating-point_standard. +// +// Template parameter: +// +// RawType: the raw floating-point type (either float or double) +template +class FloatingPoint { + public: + // Defines the unsigned integer type that has the same size as the + // floating point number. + typedef typename TypeWithSize::UInt Bits; + + // Constants. + + // # of bits in a number. + static const size_t kBitCount = 8*sizeof(RawType); + + // # of fraction bits in a number. + static const size_t kFractionBitCount = + std::numeric_limits::digits - 1; + + // # of exponent bits in a number. + static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount; + + // The mask for the sign bit. + static const Bits kSignBitMask = static_cast(1) << (kBitCount - 1); + + // The mask for the fraction bits. + static const Bits kFractionBitMask = + ~static_cast(0) >> (kExponentBitCount + 1); + + // The mask for the exponent bits. + static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask); + + // How many ULP's (Units in the Last Place) we want to tolerate when + // comparing two numbers. The larger the value, the more error we + // allow. A 0 value means that two numbers must be exactly the same + // to be considered equal. + // + // The maximum error of a single floating-point operation is 0.5 + // units in the last place. On Intel CPU's, all floating-point + // calculations are done with 80-bit precision, while double has 64 + // bits. Therefore, 4 should be enough for ordinary use. + // + // See the following article for more details on ULP: + // http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ + static const size_t kMaxUlps = 4; + + // Constructs a FloatingPoint from a raw floating-point number. + // + // On an Intel CPU, passing a non-normalized NAN (Not a Number) + // around may change its bits, although the new value is guaranteed + // to be also a NAN. Therefore, don't expect this constructor to + // preserve the bits in x when x is a NAN. + explicit FloatingPoint(const RawType& x) { u_.value_ = x; } + + // Static methods + + // Reinterprets a bit pattern as a floating-point number. + // + // This function is needed to test the AlmostEquals() method. + static RawType ReinterpretBits(const Bits bits) { + FloatingPoint fp(0); + fp.u_.bits_ = bits; + return fp.u_.value_; + } + + // Returns the floating-point number that represent positive infinity. + static RawType Infinity() { + return ReinterpretBits(kExponentBitMask); + } + + // Returns the maximum representable finite floating-point number. + static RawType Max(); + + // Non-static methods + + // Returns the bits that represents this number. + const Bits &bits() const { return u_.bits_; } + + // Returns the exponent bits of this number. + Bits exponent_bits() const { return kExponentBitMask & u_.bits_; } + + // Returns the fraction bits of this number. + Bits fraction_bits() const { return kFractionBitMask & u_.bits_; } + + // Returns the sign bit of this number. + Bits sign_bit() const { return kSignBitMask & u_.bits_; } + + // Returns true iff this is NAN (not a number). + bool is_nan() const { + // It's a NAN if the exponent bits are all ones and the fraction + // bits are not entirely zeros. + return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0); + } + + // Returns true iff this number is at most kMaxUlps ULP's away from + // rhs. In particular, this function: + // + // - returns false if either number is (or both are) NAN. + // - treats really large numbers as almost equal to infinity. + // - thinks +0.0 and -0.0 are 0 DLP's apart. + bool AlmostEquals(const FloatingPoint& rhs) const { + // The IEEE standard says that any comparison operation involving + // a NAN must return false. + if (is_nan() || rhs.is_nan()) return false; + + return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_) + <= kMaxUlps; + } + + private: + // The data type used to store the actual floating-point number. + union FloatingPointUnion { + RawType value_; // The raw floating-point number. + Bits bits_; // The bits that represent the number. + }; + + // Converts an integer from the sign-and-magnitude representation to + // the biased representation. More precisely, let N be 2 to the + // power of (kBitCount - 1), an integer x is represented by the + // unsigned number x + N. + // + // For instance, + // + // -N + 1 (the most negative number representable using + // sign-and-magnitude) is represented by 1; + // 0 is represented by N; and + // N - 1 (the biggest number representable using + // sign-and-magnitude) is represented by 2N - 1. + // + // Read http://en.wikipedia.org/wiki/Signed_number_representations + // for more details on signed number representations. + static Bits SignAndMagnitudeToBiased(const Bits &sam) { + if (kSignBitMask & sam) { + // sam represents a negative number. + return ~sam + 1; + } else { + // sam represents a positive number. + return kSignBitMask | sam; + } + } + + // Given two numbers in the sign-and-magnitude representation, + // returns the distance between them as an unsigned number. + static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1, + const Bits &sam2) { + const Bits biased1 = SignAndMagnitudeToBiased(sam1); + const Bits biased2 = SignAndMagnitudeToBiased(sam2); + return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1); + } + + FloatingPointUnion u_; +}; + +// We cannot use std::numeric_limits::max() as it clashes with the max() +// macro defined by . +template <> +inline float FloatingPoint::Max() { return FLT_MAX; } +template <> +inline double FloatingPoint::Max() { return DBL_MAX; } + +// Typedefs the instances of the FloatingPoint template class that we +// care to use. +typedef FloatingPoint Float; +typedef FloatingPoint Double; + +// In order to catch the mistake of putting tests that use different +// test fixture classes in the same test case, we need to assign +// unique IDs to fixture classes and compare them. The TypeId type is +// used to hold such IDs. The user should treat TypeId as an opaque +// type: the only operation allowed on TypeId values is to compare +// them for equality using the == operator. +typedef const void* TypeId; + +template +class TypeIdHelper { + public: + // dummy_ must not have a const type. Otherwise an overly eager + // compiler (e.g. MSVC 7.1 & 8.0) may try to merge + // TypeIdHelper::dummy_ for different Ts as an "optimization". + static bool dummy_; +}; + +template +bool TypeIdHelper::dummy_ = false; + +// GetTypeId() returns the ID of type T. Different values will be +// returned for different types. Calling the function twice with the +// same type argument is guaranteed to return the same ID. +template +TypeId GetTypeId() { + // The compiler is required to allocate a different + // TypeIdHelper::dummy_ variable for each T used to instantiate + // the template. Therefore, the address of dummy_ is guaranteed to + // be unique. + return &(TypeIdHelper::dummy_); +} + +// Returns the type ID of ::testing::Test. Always call this instead +// of GetTypeId< ::testing::Test>() to get the type ID of +// ::testing::Test, as the latter may give the wrong result due to a +// suspected linker bug when compiling Google Test as a Mac OS X +// framework. +GTEST_API_ TypeId GetTestTypeId(); + +// Defines the abstract factory interface that creates instances +// of a Test object. +class TestFactoryBase { + public: + virtual ~TestFactoryBase() {} + + // Creates a test instance to run. The instance is both created and destroyed + // within TestInfoImpl::Run() + virtual Test* CreateTest() = 0; + + protected: + TestFactoryBase() {} + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestFactoryBase); +}; + +// This class provides implementation of TeastFactoryBase interface. +// It is used in TEST and TEST_F macros. +template +class TestFactoryImpl : public TestFactoryBase { + public: + virtual Test* CreateTest() { return new TestClass; } +}; + +#if GTEST_OS_WINDOWS + +// Predicate-formatters for implementing the HRESULT checking macros +// {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED} +// We pass a long instead of HRESULT to avoid causing an +// include dependency for the HRESULT type. +GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr, + long hr); // NOLINT +GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr, + long hr); // NOLINT + +#endif // GTEST_OS_WINDOWS + +// Types of SetUpTestCase() and TearDownTestCase() functions. +typedef void (*SetUpTestCaseFunc)(); +typedef void (*TearDownTestCaseFunc)(); + +// Creates a new TestInfo object and registers it with Google Test; +// returns the created object. +// +// Arguments: +// +// test_case_name: name of the test case +// name: name of the test +// type_param the name of the test's type parameter, or NULL if +// this is not a typed or a type-parameterized test. +// value_param text representation of the test's value parameter, +// or NULL if this is not a type-parameterized test. +// fixture_class_id: ID of the test fixture class +// set_up_tc: pointer to the function that sets up the test case +// tear_down_tc: pointer to the function that tears down the test case +// factory: pointer to the factory that creates a test object. +// The newly created TestInfo instance will assume +// ownership of the factory object. +GTEST_API_ TestInfo* MakeAndRegisterTestInfo( + const char* test_case_name, + const char* name, + const char* type_param, + const char* value_param, + TypeId fixture_class_id, + SetUpTestCaseFunc set_up_tc, + TearDownTestCaseFunc tear_down_tc, + TestFactoryBase* factory); + +// If *pstr starts with the given prefix, modifies *pstr to be right +// past the prefix and returns true; otherwise leaves *pstr unchanged +// and returns false. None of pstr, *pstr, and prefix can be NULL. +GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr); + +#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +// State of the definition of a type-parameterized test case. +class GTEST_API_ TypedTestCasePState { + public: + TypedTestCasePState() : registered_(false) {} + + // Adds the given test name to defined_test_names_ and return true + // if the test case hasn't been registered; otherwise aborts the + // program. + bool AddTestName(const char* file, int line, const char* case_name, + const char* test_name) { + if (registered_) { + fprintf(stderr, "%s Test %s must be defined before " + "REGISTER_TYPED_TEST_CASE_P(%s, ...).\n", + FormatFileLocation(file, line).c_str(), test_name, case_name); + fflush(stderr); + posix::Abort(); + } + defined_test_names_.insert(test_name); + return true; + } + + // Verifies that registered_tests match the test names in + // defined_test_names_; returns registered_tests if successful, or + // aborts the program otherwise. + const char* VerifyRegisteredTestNames( + const char* file, int line, const char* registered_tests); + + private: + bool registered_; + ::std::set defined_test_names_; +}; + +// Skips to the first non-space char after the first comma in 'str'; +// returns NULL if no comma is found in 'str'. +inline const char* SkipComma(const char* str) { + const char* comma = strchr(str, ','); + if (comma == NULL) { + return NULL; + } + while (IsSpace(*(++comma))) {} + return comma; +} + +// Returns the prefix of 'str' before the first comma in it; returns +// the entire string if it contains no comma. +inline std::string GetPrefixUntilComma(const char* str) { + const char* comma = strchr(str, ','); + return comma == NULL ? str : std::string(str, comma); +} + +// TypeParameterizedTest::Register() +// registers a list of type-parameterized tests with Google Test. The +// return value is insignificant - we just need to return something +// such that we can call this function in a namespace scope. +// +// Implementation note: The GTEST_TEMPLATE_ macro declares a template +// template parameter. It's defined in gtest-type-util.h. +template +class TypeParameterizedTest { + public: + // 'index' is the index of the test in the type list 'Types' + // specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase, + // Types). Valid values for 'index' are [0, N - 1] where N is the + // length of Types. + static bool Register(const char* prefix, const char* case_name, + const char* test_names, int index) { + typedef typename Types::Head Type; + typedef Fixture FixtureClass; + typedef typename GTEST_BIND_(TestSel, Type) TestClass; + + // First, registers the first type-parameterized test in the type + // list. + MakeAndRegisterTestInfo( + (std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name + "/" + + StreamableToString(index)).c_str(), + GetPrefixUntilComma(test_names).c_str(), + GetTypeName().c_str(), + NULL, // No value parameter. + GetTypeId(), + TestClass::SetUpTestCase, + TestClass::TearDownTestCase, + new TestFactoryImpl); + + // Next, recurses (at compile time) with the tail of the type list. + return TypeParameterizedTest + ::Register(prefix, case_name, test_names, index + 1); + } +}; + +// The base case for the compile time recursion. +template +class TypeParameterizedTest { + public: + static bool Register(const char* /*prefix*/, const char* /*case_name*/, + const char* /*test_names*/, int /*index*/) { + return true; + } +}; + +// TypeParameterizedTestCase::Register() +// registers *all combinations* of 'Tests' and 'Types' with Google +// Test. The return value is insignificant - we just need to return +// something such that we can call this function in a namespace scope. +template +class TypeParameterizedTestCase { + public: + static bool Register(const char* prefix, const char* case_name, + const char* test_names) { + typedef typename Tests::Head Head; + + // First, register the first test in 'Test' for each type in 'Types'. + TypeParameterizedTest::Register( + prefix, case_name, test_names, 0); + + // Next, recurses (at compile time) with the tail of the test list. + return TypeParameterizedTestCase + ::Register(prefix, case_name, SkipComma(test_names)); + } +}; + +// The base case for the compile time recursion. +template +class TypeParameterizedTestCase { + public: + static bool Register(const char* /*prefix*/, const char* /*case_name*/, + const char* /*test_names*/) { + return true; + } +}; + +#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P + +// Returns the current OS stack trace as an std::string. +// +// The maximum number of stack frames to be included is specified by +// the gtest_stack_trace_depth flag. The skip_count parameter +// specifies the number of top frames to be skipped, which doesn't +// count against the number of frames to be included. +// +// For example, if Foo() calls Bar(), which in turn calls +// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in +// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't. +GTEST_API_ std::string GetCurrentOsStackTraceExceptTop( + UnitTest* unit_test, int skip_count); + +// Helpers for suppressing warnings on unreachable code or constant +// condition. + +// Always returns true. +GTEST_API_ bool AlwaysTrue(); + +// Always returns false. +inline bool AlwaysFalse() { return !AlwaysTrue(); } + +// Helper for suppressing false warning from Clang on a const char* +// variable declared in a conditional expression always being NULL in +// the else branch. +struct GTEST_API_ ConstCharPtr { + ConstCharPtr(const char* str) : value(str) {} + operator bool() const { return true; } + const char* value; +}; + +// A simple Linear Congruential Generator for generating random +// numbers with a uniform distribution. Unlike rand() and srand(), it +// doesn't use global state (and therefore can't interfere with user +// code). Unlike rand_r(), it's portable. An LCG isn't very random, +// but it's good enough for our purposes. +class GTEST_API_ Random { + public: + static const UInt32 kMaxRange = 1u << 31; + + explicit Random(UInt32 seed) : state_(seed) {} + + void Reseed(UInt32 seed) { state_ = seed; } + + // Generates a random number from [0, range). Crashes if 'range' is + // 0 or greater than kMaxRange. + UInt32 Generate(UInt32 range); + + private: + UInt32 state_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(Random); +}; + +// Defining a variable of type CompileAssertTypesEqual will cause a +// compiler error iff T1 and T2 are different types. +template +struct CompileAssertTypesEqual; + +template +struct CompileAssertTypesEqual { +}; + +// Removes the reference from a type if it is a reference type, +// otherwise leaves it unchanged. This is the same as +// tr1::remove_reference, which is not widely available yet. +template +struct RemoveReference { typedef T type; }; // NOLINT +template +struct RemoveReference { typedef T type; }; // NOLINT + +// A handy wrapper around RemoveReference that works when the argument +// T depends on template parameters. +#define GTEST_REMOVE_REFERENCE_(T) \ + typename ::testing::internal::RemoveReference::type + +// Removes const from a type if it is a const type, otherwise leaves +// it unchanged. This is the same as tr1::remove_const, which is not +// widely available yet. +template +struct RemoveConst { typedef T type; }; // NOLINT +template +struct RemoveConst { typedef T type; }; // NOLINT + +// MSVC 8.0, Sun C++, and IBM XL C++ have a bug which causes the above +// definition to fail to remove the const in 'const int[3]' and 'const +// char[3][4]'. The following specialization works around the bug. +template +struct RemoveConst { + typedef typename RemoveConst::type type[N]; +}; + +#if defined(_MSC_VER) && _MSC_VER < 1400 +// This is the only specialization that allows VC++ 7.1 to remove const in +// 'const int[3] and 'const int[3][4]'. However, it causes trouble with GCC +// and thus needs to be conditionally compiled. +template +struct RemoveConst { + typedef typename RemoveConst::type type[N]; +}; +#endif + +// A handy wrapper around RemoveConst that works when the argument +// T depends on template parameters. +#define GTEST_REMOVE_CONST_(T) \ + typename ::testing::internal::RemoveConst::type + +// Turns const U&, U&, const U, and U all into U. +#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \ + GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T)) + +// Adds reference to a type if it is not a reference type, +// otherwise leaves it unchanged. This is the same as +// tr1::add_reference, which is not widely available yet. +template +struct AddReference { typedef T& type; }; // NOLINT +template +struct AddReference { typedef T& type; }; // NOLINT + +// A handy wrapper around AddReference that works when the argument T +// depends on template parameters. +#define GTEST_ADD_REFERENCE_(T) \ + typename ::testing::internal::AddReference::type + +// Adds a reference to const on top of T as necessary. For example, +// it transforms +// +// char ==> const char& +// const char ==> const char& +// char& ==> const char& +// const char& ==> const char& +// +// The argument T must depend on some template parameters. +#define GTEST_REFERENCE_TO_CONST_(T) \ + GTEST_ADD_REFERENCE_(const GTEST_REMOVE_REFERENCE_(T)) + +// ImplicitlyConvertible::value is a compile-time bool +// constant that's true iff type From can be implicitly converted to +// type To. +template +class ImplicitlyConvertible { + private: + // We need the following helper functions only for their types. + // They have no implementations. + + // MakeFrom() is an expression whose type is From. We cannot simply + // use From(), as the type From may not have a public default + // constructor. + static From MakeFrom(); + + // These two functions are overloaded. Given an expression + // Helper(x), the compiler will pick the first version if x can be + // implicitly converted to type To; otherwise it will pick the + // second version. + // + // The first version returns a value of size 1, and the second + // version returns a value of size 2. Therefore, by checking the + // size of Helper(x), which can be done at compile time, we can tell + // which version of Helper() is used, and hence whether x can be + // implicitly converted to type To. + static char Helper(To); + static char (&Helper(...))[2]; // NOLINT + + // We have to put the 'public' section after the 'private' section, + // or MSVC refuses to compile the code. + public: + // MSVC warns about implicitly converting from double to int for + // possible loss of data, so we need to temporarily disable the + // warning. +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4244) // Temporarily disables warning 4244. + + static const bool value = + sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1; +# pragma warning(pop) // Restores the warning state. +#elif defined(__BORLANDC__) + // C++Builder cannot use member overload resolution during template + // instantiation. The simplest workaround is to use its C++0x type traits + // functions (C++Builder 2009 and above only). + static const bool value = __is_convertible(From, To); +#else + static const bool value = + sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1; +#endif // _MSV_VER +}; +template +const bool ImplicitlyConvertible::value; + +// IsAProtocolMessage::value is a compile-time bool constant that's +// true iff T is type ProtocolMessage, proto2::Message, or a subclass +// of those. +template +struct IsAProtocolMessage + : public bool_constant< + ImplicitlyConvertible::value || + ImplicitlyConvertible::value> { +}; + +// When the compiler sees expression IsContainerTest(0), if C is an +// STL-style container class, the first overload of IsContainerTest +// will be viable (since both C::iterator* and C::const_iterator* are +// valid types and NULL can be implicitly converted to them). It will +// be picked over the second overload as 'int' is a perfect match for +// the type of argument 0. If C::iterator or C::const_iterator is not +// a valid type, the first overload is not viable, and the second +// overload will be picked. Therefore, we can determine whether C is +// a container class by checking the type of IsContainerTest(0). +// The value of the expression is insignificant. +// +// Note that we look for both C::iterator and C::const_iterator. The +// reason is that C++ injects the name of a class as a member of the +// class itself (e.g. you can refer to class iterator as either +// 'iterator' or 'iterator::iterator'). If we look for C::iterator +// only, for example, we would mistakenly think that a class named +// iterator is an STL container. +// +// Also note that the simpler approach of overloading +// IsContainerTest(typename C::const_iterator*) and +// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++. +typedef int IsContainer; +template +IsContainer IsContainerTest(int /* dummy */, + typename C::iterator* /* it */ = NULL, + typename C::const_iterator* /* const_it */ = NULL) { + return 0; +} + +typedef char IsNotContainer; +template +IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; } + +// EnableIf::type is void when 'Cond' is true, and +// undefined when 'Cond' is false. To use SFINAE to make a function +// overload only apply when a particular expression is true, add +// "typename EnableIf::type* = 0" as the last parameter. +template struct EnableIf; +template<> struct EnableIf { typedef void type; }; // NOLINT + +// Utilities for native arrays. + +// ArrayEq() compares two k-dimensional native arrays using the +// elements' operator==, where k can be any integer >= 0. When k is +// 0, ArrayEq() degenerates into comparing a single pair of values. + +template +bool ArrayEq(const T* lhs, size_t size, const U* rhs); + +// This generic version is used when k is 0. +template +inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; } + +// This overload is used when k >= 1. +template +inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) { + return internal::ArrayEq(lhs, N, rhs); +} + +// This helper reduces code bloat. If we instead put its logic inside +// the previous ArrayEq() function, arrays with different sizes would +// lead to different copies of the template code. +template +bool ArrayEq(const T* lhs, size_t size, const U* rhs) { + for (size_t i = 0; i != size; i++) { + if (!internal::ArrayEq(lhs[i], rhs[i])) + return false; + } + return true; +} + +// Finds the first element in the iterator range [begin, end) that +// equals elem. Element may be a native array type itself. +template +Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) { + for (Iter it = begin; it != end; ++it) { + if (internal::ArrayEq(*it, elem)) + return it; + } + return end; +} + +// CopyArray() copies a k-dimensional native array using the elements' +// operator=, where k can be any integer >= 0. When k is 0, +// CopyArray() degenerates into copying a single value. + +template +void CopyArray(const T* from, size_t size, U* to); + +// This generic version is used when k is 0. +template +inline void CopyArray(const T& from, U* to) { *to = from; } + +// This overload is used when k >= 1. +template +inline void CopyArray(const T(&from)[N], U(*to)[N]) { + internal::CopyArray(from, N, *to); +} + +// This helper reduces code bloat. If we instead put its logic inside +// the previous CopyArray() function, arrays with different sizes +// would lead to different copies of the template code. +template +void CopyArray(const T* from, size_t size, U* to) { + for (size_t i = 0; i != size; i++) { + internal::CopyArray(from[i], to + i); + } +} + +// The relation between an NativeArray object (see below) and the +// native array it represents. +enum RelationToSource { + kReference, // The NativeArray references the native array. + kCopy // The NativeArray makes a copy of the native array and + // owns the copy. +}; + +// Adapts a native array to a read-only STL-style container. Instead +// of the complete STL container concept, this adaptor only implements +// members useful for Google Mock's container matchers. New members +// should be added as needed. To simplify the implementation, we only +// support Element being a raw type (i.e. having no top-level const or +// reference modifier). It's the client's responsibility to satisfy +// this requirement. Element can be an array type itself (hence +// multi-dimensional arrays are supported). +template +class NativeArray { + public: + // STL-style container typedefs. + typedef Element value_type; + typedef Element* iterator; + typedef const Element* const_iterator; + + // Constructs from a native array. + NativeArray(const Element* array, size_t count, RelationToSource relation) { + Init(array, count, relation); + } + + // Copy constructor. + NativeArray(const NativeArray& rhs) { + Init(rhs.array_, rhs.size_, rhs.relation_to_source_); + } + + ~NativeArray() { + // Ensures that the user doesn't instantiate NativeArray with a + // const or reference type. + static_cast(StaticAssertTypeEqHelper()); + if (relation_to_source_ == kCopy) + delete[] array_; + } + + // STL-style container methods. + size_t size() const { return size_; } + const_iterator begin() const { return array_; } + const_iterator end() const { return array_ + size_; } + bool operator==(const NativeArray& rhs) const { + return size() == rhs.size() && + ArrayEq(begin(), size(), rhs.begin()); + } + + private: + // Initializes this object; makes a copy of the input array if + // 'relation' is kCopy. + void Init(const Element* array, size_t a_size, RelationToSource relation) { + if (relation == kReference) { + array_ = array; + } else { + Element* const copy = new Element[a_size]; + CopyArray(array, a_size, copy); + array_ = copy; + } + size_ = a_size; + relation_to_source_ = relation; + } + + const Element* array_; + size_t size_; + RelationToSource relation_to_source_; + + GTEST_DISALLOW_ASSIGN_(NativeArray); +}; + +} // namespace internal +} // namespace testing + +#define GTEST_MESSAGE_AT_(file, line, message, result_type) \ + ::testing::internal::AssertHelper(result_type, file, line, message) \ + = ::testing::Message() + +#define GTEST_MESSAGE_(message, result_type) \ + GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type) + +#define GTEST_FATAL_FAILURE_(message) \ + return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure) + +#define GTEST_NONFATAL_FAILURE_(message) \ + GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure) + +#define GTEST_SUCCESS_(message) \ + GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess) + +// Suppresses MSVC warnings 4072 (unreachable code) for the code following +// statement if it returns or throws (or doesn't return or throw in some +// situations). +#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \ + if (::testing::internal::AlwaysTrue()) { statement; } + +#define GTEST_TEST_THROW_(statement, expected_exception, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::ConstCharPtr gtest_msg = "") { \ + bool gtest_caught_expected = false; \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } \ + catch (expected_exception const&) { \ + gtest_caught_expected = true; \ + } \ + catch (...) { \ + gtest_msg.value = \ + "Expected: " #statement " throws an exception of type " \ + #expected_exception ".\n Actual: it throws a different type."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ + } \ + if (!gtest_caught_expected) { \ + gtest_msg.value = \ + "Expected: " #statement " throws an exception of type " \ + #expected_exception ".\n Actual: it throws nothing."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \ + fail(gtest_msg.value) + +#define GTEST_TEST_NO_THROW_(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } \ + catch (...) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \ + fail("Expected: " #statement " doesn't throw an exception.\n" \ + " Actual: it throws.") + +#define GTEST_TEST_ANY_THROW_(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + bool gtest_caught_any = false; \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } \ + catch (...) { \ + gtest_caught_any = true; \ + } \ + if (!gtest_caught_any) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \ + fail("Expected: " #statement " throws an exception.\n" \ + " Actual: it doesn't.") + + +// Implements Boolean test assertions such as EXPECT_TRUE. expression can be +// either a boolean expression or an AssertionResult. text is a textual +// represenation of expression as it was passed into the EXPECT_TRUE. +#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (const ::testing::AssertionResult gtest_ar_ = \ + ::testing::AssertionResult(expression)) \ + ; \ + else \ + fail(::testing::internal::GetBoolAssertionFailureMessage(\ + gtest_ar_, text, #actual, #expected).c_str()) + +#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + ::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \ + fail("Expected: " #statement " doesn't generate new fatal " \ + "failures in the current thread.\n" \ + " Actual: it does.") + +// Expands to the name of the class that implements the given test. +#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ + test_case_name##_##test_name##_Test + +// Helper macro for defining tests. +#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\ +class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\ + public:\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\ + private:\ + virtual void TestBody();\ + static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\ + GTEST_DISALLOW_COPY_AND_ASSIGN_(\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\ +};\ +\ +::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\ + ::test_info_ =\ + ::testing::internal::MakeAndRegisterTestInfo(\ + #test_case_name, #test_name, NULL, NULL, \ + (parent_id), \ + parent_class::SetUpTestCase, \ + parent_class::TearDownTestCase, \ + new ::testing::internal::TestFactoryImpl<\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\ +void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ +// 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 +// 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) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines the public API for death tests. It is +// #included by gtest.h so a user doesn't need to include this +// directly. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ + +// 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 +// 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. +// +// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) +// +// The Google C++ Testing Framework (Google Test) +// +// This header file defines internal utilities needed for implementing +// death tests. They are subject to change without notice. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ + + +#include + +namespace testing { +namespace internal { + +GTEST_DECLARE_string_(internal_run_death_test); + +// Names of the flags (needed for parsing Google Test flags). +const char kDeathTestStyleFlag[] = "death_test_style"; +const char kDeathTestUseFork[] = "death_test_use_fork"; +const char kInternalRunDeathTestFlag[] = "internal_run_death_test"; + +#if GTEST_HAS_DEATH_TEST + +// DeathTest is a class that hides much of the complexity of the +// GTEST_DEATH_TEST_ macro. It is abstract; its static Create method +// returns a concrete class that depends on the prevailing death test +// style, as defined by the --gtest_death_test_style and/or +// --gtest_internal_run_death_test flags. + +// In describing the results of death tests, these terms are used with +// the corresponding definitions: +// +// exit status: The integer exit information in the format specified +// by wait(2) +// exit code: The integer code passed to exit(3), _exit(2), or +// returned from main() +class GTEST_API_ DeathTest { + public: + // Create returns false if there was an error determining the + // appropriate action to take for the current death test; for example, + // if the gtest_death_test_style flag is set to an invalid value. + // The LastMessage method will return a more detailed message in that + // case. Otherwise, the DeathTest pointer pointed to by the "test" + // argument is set. If the death test should be skipped, the pointer + // is set to NULL; otherwise, it is set to the address of a new concrete + // DeathTest object that controls the execution of the current test. + static bool Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test); + DeathTest(); + virtual ~DeathTest() { } + + // A helper class that aborts a death test when it's deleted. + class ReturnSentinel { + public: + explicit ReturnSentinel(DeathTest* test) : test_(test) { } + ~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); } + private: + DeathTest* const test_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel); + } GTEST_ATTRIBUTE_UNUSED_; + + // An enumeration of possible roles that may be taken when a death + // test is encountered. EXECUTE means that the death test logic should + // be executed immediately. OVERSEE means that the program should prepare + // the appropriate environment for a child process to execute the death + // test, then wait for it to complete. + enum TestRole { OVERSEE_TEST, EXECUTE_TEST }; + + // An enumeration of the three reasons that a test might be aborted. + enum AbortReason { + TEST_ENCOUNTERED_RETURN_STATEMENT, + TEST_THREW_EXCEPTION, + TEST_DID_NOT_DIE + }; + + // Assumes one of the above roles. + virtual TestRole AssumeRole() = 0; + + // Waits for the death test to finish and returns its status. + virtual int Wait() = 0; + + // Returns true if the death test passed; that is, the test process + // exited during the test, its exit status matches a user-supplied + // predicate, and its stderr output matches a user-supplied regular + // expression. + // The user-supplied predicate may be a macro expression rather + // than a function pointer or functor, or else Wait and Passed could + // be combined. + virtual bool Passed(bool exit_status_ok) = 0; + + // Signals that the death test did not die as expected. + virtual void Abort(AbortReason reason) = 0; + + // Returns a human-readable outcome message regarding the outcome of + // the last death test. + static const char* LastMessage(); + + static void set_last_death_test_message(const std::string& message); + + private: + // A string containing a description of the outcome of the last death test. + static std::string last_death_test_message_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest); +}; + +// Factory interface for death tests. May be mocked out for testing. +class DeathTestFactory { + public: + virtual ~DeathTestFactory() { } + virtual bool Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test) = 0; +}; + +// A concrete DeathTestFactory implementation for normal use. +class DefaultDeathTestFactory : public DeathTestFactory { + public: + virtual bool Create(const char* statement, const RE* regex, + const char* file, int line, DeathTest** test); +}; + +// Returns true if exit_status describes a process that was terminated +// by a signal, or exited normally with a nonzero exit code. +GTEST_API_ bool ExitedUnsuccessfully(int exit_status); + +// Traps C++ exceptions escaping statement and reports them as test +// failures. Note that trapping SEH exceptions is not implemented here. +# if GTEST_HAS_EXCEPTIONS +# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } catch (const ::std::exception& gtest_exception) { \ + fprintf(\ + stderr, \ + "\n%s: Caught std::exception-derived exception escaping the " \ + "death test statement. Exception message: %s\n", \ + ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \ + gtest_exception.what()); \ + fflush(stderr); \ + death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \ + } catch (...) { \ + death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \ + } + +# else +# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) + +# endif + +// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*, +// ASSERT_EXIT*, and EXPECT_EXIT*. +# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + const ::testing::internal::RE& gtest_regex = (regex); \ + ::testing::internal::DeathTest* gtest_dt; \ + if (!::testing::internal::DeathTest::Create(#statement, >est_regex, \ + __FILE__, __LINE__, >est_dt)) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ + } \ + if (gtest_dt != NULL) { \ + ::testing::internal::scoped_ptr< ::testing::internal::DeathTest> \ + gtest_dt_ptr(gtest_dt); \ + switch (gtest_dt->AssumeRole()) { \ + case ::testing::internal::DeathTest::OVERSEE_TEST: \ + if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \ + goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ + } \ + break; \ + case ::testing::internal::DeathTest::EXECUTE_TEST: { \ + ::testing::internal::DeathTest::ReturnSentinel \ + gtest_sentinel(gtest_dt); \ + GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \ + gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \ + break; \ + } \ + default: \ + break; \ + } \ + } \ + } else \ + GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__): \ + fail(::testing::internal::DeathTest::LastMessage()) +// The symbol "fail" here expands to something into which a message +// can be streamed. + +// This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in +// NDEBUG mode. In this case we need the statements to be executed, the regex is +// ignored, and the macro must accept a streamed message even though the message +// is never printed. +# define GTEST_EXECUTE_STATEMENT_(statement, regex) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } else \ + ::testing::Message() + +// A class representing the parsed contents of the +// --gtest_internal_run_death_test flag, as it existed when +// RUN_ALL_TESTS was called. +class InternalRunDeathTestFlag { + public: + InternalRunDeathTestFlag(const std::string& a_file, + int a_line, + int an_index, + int a_write_fd) + : file_(a_file), line_(a_line), index_(an_index), + write_fd_(a_write_fd) {} + + ~InternalRunDeathTestFlag() { + if (write_fd_ >= 0) + posix::Close(write_fd_); + } + + const std::string& file() const { return file_; } + int line() const { return line_; } + int index() const { return index_; } + int write_fd() const { return write_fd_; } + + private: + std::string file_; + int line_; + int index_; + int write_fd_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag); +}; + +// Returns a newly created InternalRunDeathTestFlag object with fields +// initialized from the GTEST_FLAG(internal_run_death_test) flag if +// the flag is specified; otherwise returns NULL. +InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag(); + +#else // GTEST_HAS_DEATH_TEST + +// This macro is used for implementing macros such as +// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where +// death tests are not supported. Those macros must compile on such systems +// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on +// systems that support death tests. This allows one to write such a macro +// on a system that does not support death tests and be sure that it will +// compile on a death-test supporting system. +// +// Parameters: +// statement - A statement that a macro such as EXPECT_DEATH would test +// for program termination. This macro has to make sure this +// statement is compiled but not executed, to ensure that +// EXPECT_DEATH_IF_SUPPORTED compiles with a certain +// parameter iff EXPECT_DEATH compiles with it. +// regex - A regex that a macro such as EXPECT_DEATH would use to test +// the output of statement. This parameter has to be +// compiled but not evaluated by this macro, to ensure that +// this macro only accepts expressions that a macro such as +// EXPECT_DEATH would accept. +// terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED +// and a return statement for ASSERT_DEATH_IF_SUPPORTED. +// This ensures that ASSERT_DEATH_IF_SUPPORTED will not +// compile inside functions where ASSERT_DEATH doesn't +// compile. +// +// The branch that has an always false condition is used to ensure that +// statement and regex are compiled (and thus syntactically correct) but +// never executed. The unreachable code macro protects the terminator +// statement from generating an 'unreachable code' warning in case +// statement unconditionally returns or throws. The Message constructor at +// the end allows the syntax of streaming additional messages into the +// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH. +# define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::AlwaysTrue()) { \ + GTEST_LOG_(WARNING) \ + << "Death tests are not supported on this platform.\n" \ + << "Statement '" #statement "' cannot be verified."; \ + } else if (::testing::internal::AlwaysFalse()) { \ + ::testing::internal::RE::PartialMatch(".*", (regex)); \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + terminator; \ + } else \ + ::testing::Message() + +#endif // GTEST_HAS_DEATH_TEST + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ + +namespace testing { + +// This flag controls the style of death tests. Valid values are "threadsafe", +// meaning that the death test child process will re-execute the test binary +// from the start, running only a single death test, or "fast", +// meaning that the child process will execute the test logic immediately +// after forking. +GTEST_DECLARE_string_(death_test_style); + +#if GTEST_HAS_DEATH_TEST + +namespace internal { + +// Returns a Boolean value indicating whether the caller is currently +// executing in the context of the death test child process. Tools such as +// Valgrind heap checkers may need this to modify their behavior in death +// tests. IMPORTANT: This is an internal utility. Using it may break the +// implementation of death tests. User code MUST NOT use it. +GTEST_API_ bool InDeathTestChild(); + +} // namespace internal + +// The following macros are useful for writing death tests. + +// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is +// executed: +// +// 1. It generates a warning if there is more than one active +// thread. This is because it's safe to fork() or clone() only +// when there is a single thread. +// +// 2. The parent process clone()s a sub-process and runs the death +// test in it; the sub-process exits with code 0 at the end of the +// death test, if it hasn't exited already. +// +// 3. The parent process waits for the sub-process to terminate. +// +// 4. The parent process checks the exit code and error message of +// the sub-process. +// +// Examples: +// +// ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number"); +// for (int i = 0; i < 5; i++) { +// EXPECT_DEATH(server.ProcessRequest(i), +// "Invalid request .* in ProcessRequest()") +// << "Failed to die on request " << i; +// } +// +// ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting"); +// +// bool KilledBySIGHUP(int exit_code) { +// return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP; +// } +// +// ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!"); +// +// On the regular expressions used in death tests: +// +// On POSIX-compliant systems (*nix), we use the library, +// which uses the POSIX extended regex syntax. +// +// On other platforms (e.g. Windows), we only support a simple regex +// syntax implemented as part of Google Test. This limited +// implementation should be enough most of the time when writing +// death tests; though it lacks many features you can find in PCRE +// or POSIX extended regex syntax. For example, we don't support +// union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and +// repetition count ("x{5,7}"), among others. +// +// Below is the syntax that we do support. We chose it to be a +// subset of both PCRE and POSIX extended regex, so it's easy to +// learn wherever you come from. In the following: 'A' denotes a +// literal character, period (.), or a single \\ escape sequence; +// 'x' and 'y' denote regular expressions; 'm' and 'n' are for +// natural numbers. +// +// c matches any literal character c +// \\d matches any decimal digit +// \\D matches any character that's not a decimal digit +// \\f matches \f +// \\n matches \n +// \\r matches \r +// \\s matches any ASCII whitespace, including \n +// \\S matches any character that's not a whitespace +// \\t matches \t +// \\v matches \v +// \\w matches any letter, _, or decimal digit +// \\W matches any character that \\w doesn't match +// \\c matches any literal character c, which must be a punctuation +// . matches any single character except \n +// A? matches 0 or 1 occurrences of A +// A* matches 0 or many occurrences of A +// A+ matches 1 or many occurrences of A +// ^ matches the beginning of a string (not that of each line) +// $ matches the end of a string (not that of each line) +// xy matches x followed by y +// +// If you accidentally use PCRE or POSIX extended regex features +// not implemented by us, you will get a run-time failure. In that +// case, please try to rewrite your regular expression within the +// above syntax. +// +// This implementation is *not* meant to be as highly tuned or robust +// as a compiled regex library, but should perform well enough for a +// death test, which already incurs significant overhead by launching +// a child process. +// +// Known caveats: +// +// A "threadsafe" style death test obtains the path to the test +// program from argv[0] and re-executes it in the sub-process. For +// simplicity, the current implementation doesn't search the PATH +// when launching the sub-process. This means that the user must +// invoke the test program via a path that contains at least one +// path separator (e.g. path/to/foo_test and +// /absolute/path/to/bar_test are fine, but foo_test is not). This +// is rarely a problem as people usually don't put the test binary +// directory in PATH. +// +// TODO(wan@google.com): make thread-safe death tests search the PATH. + +// Asserts that a given statement causes the program to exit, with an +// integer exit status that satisfies predicate, and emitting error output +// that matches regex. +# define ASSERT_EXIT(statement, predicate, regex) \ + GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_) + +// Like ASSERT_EXIT, but continues on to successive tests in the +// test case, if any: +# define EXPECT_EXIT(statement, predicate, regex) \ + GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_) + +// Asserts that a given statement causes the program to exit, either by +// explicitly exiting with a nonzero exit code or being killed by a +// signal, and emitting error output that matches regex. +# define ASSERT_DEATH(statement, regex) \ + ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) + +// Like ASSERT_DEATH, but continues on to successive tests in the +// test case, if any: +# define EXPECT_DEATH(statement, regex) \ + EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) + +// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*: + +// Tests that an exit code describes a normal exit with a given exit code. +class GTEST_API_ ExitedWithCode { + public: + explicit ExitedWithCode(int exit_code); + bool operator()(int exit_status) const; + private: + // No implementation - assignment is unsupported. + void operator=(const ExitedWithCode& other); + + const int exit_code_; +}; + +# if !GTEST_OS_WINDOWS +// Tests that an exit code describes an exit due to termination by a +// given signal. +class GTEST_API_ KilledBySignal { + public: + explicit KilledBySignal(int signum); + bool operator()(int exit_status) const; + private: + const int signum_; +}; +# endif // !GTEST_OS_WINDOWS + +// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode. +// The death testing framework causes this to have interesting semantics, +// since the sideeffects of the call are only visible in opt mode, and not +// in debug mode. +// +// In practice, this can be used to test functions that utilize the +// LOG(DFATAL) macro using the following style: +// +// int DieInDebugOr12(int* sideeffect) { +// if (sideeffect) { +// *sideeffect = 12; +// } +// LOG(DFATAL) << "death"; +// return 12; +// } +// +// TEST(TestCase, TestDieOr12WorksInDgbAndOpt) { +// int sideeffect = 0; +// // Only asserts in dbg. +// EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death"); +// +// #ifdef NDEBUG +// // opt-mode has sideeffect visible. +// EXPECT_EQ(12, sideeffect); +// #else +// // dbg-mode no visible sideeffect. +// EXPECT_EQ(0, sideeffect); +// #endif +// } +// +// This will assert that DieInDebugReturn12InOpt() crashes in debug +// mode, usually due to a DCHECK or LOG(DFATAL), but returns the +// appropriate fallback value (12 in this case) in opt mode. If you +// need to test that a function has appropriate side-effects in opt +// mode, include assertions against the side-effects. A general +// pattern for this is: +// +// EXPECT_DEBUG_DEATH({ +// // Side-effects here will have an effect after this statement in +// // opt mode, but none in debug mode. +// EXPECT_EQ(12, DieInDebugOr12(&sideeffect)); +// }, "death"); +// +# ifdef NDEBUG + +# define EXPECT_DEBUG_DEATH(statement, regex) \ + GTEST_EXECUTE_STATEMENT_(statement, regex) + +# define ASSERT_DEBUG_DEATH(statement, regex) \ + GTEST_EXECUTE_STATEMENT_(statement, regex) + +# else + +# define EXPECT_DEBUG_DEATH(statement, regex) \ + EXPECT_DEATH(statement, regex) + +# define ASSERT_DEBUG_DEATH(statement, regex) \ + ASSERT_DEATH(statement, regex) + +# endif // NDEBUG for EXPECT_DEBUG_DEATH +#endif // GTEST_HAS_DEATH_TEST + +// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and +// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if +// death tests are supported; otherwise they just issue a warning. This is +// useful when you are combining death test assertions with normal test +// assertions in one test. +#if GTEST_HAS_DEATH_TEST +# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ + EXPECT_DEATH(statement, regex) +# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \ + ASSERT_DEATH(statement, regex) +#else +# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ + GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, ) +# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \ + GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return) +#endif + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ +// This file was GENERATED by command: +// pump.py gtest-param-test.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2008, 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. +// +// Authors: vladl@google.com (Vlad Losev) +// +// Macros and functions for implementing parameterized tests +// in Google C++ Testing Framework (Google Test) +// +// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! +// +#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ + + +// Value-parameterized tests allow you to test your code with different +// parameters without writing multiple copies of the same test. +// +// Here is how you use value-parameterized tests: + +#if 0 + +// To write value-parameterized tests, first you should define a fixture +// class. It is usually derived from testing::TestWithParam (see below for +// another inheritance scheme that's sometimes useful in more complicated +// class hierarchies), where the type of your parameter values. +// TestWithParam is itself derived from testing::Test. T can be any +// copyable type. If it's a raw pointer, you are responsible for managing the +// lifespan of the pointed values. + +class FooTest : public ::testing::TestWithParam { + // You can implement all the usual class fixture members here. +}; + +// Then, use the TEST_P macro to define as many parameterized tests +// for this fixture as you want. The _P suffix is for "parameterized" +// or "pattern", whichever you prefer to think. + +TEST_P(FooTest, DoesBlah) { + // Inside a test, access the test parameter with the GetParam() method + // of the TestWithParam class: + EXPECT_TRUE(foo.Blah(GetParam())); + ... +} + +TEST_P(FooTest, HasBlahBlah) { + ... +} + +// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test +// case with any set of parameters you want. Google Test defines a number +// of functions for generating test parameters. They return what we call +// (surprise!) parameter generators. Here is a summary of them, which +// are all in the testing namespace: +// +// +// Range(begin, end [, step]) - Yields values {begin, begin+step, +// begin+step+step, ...}. The values do not +// include end. step defaults to 1. +// Values(v1, v2, ..., vN) - Yields values {v1, v2, ..., vN}. +// ValuesIn(container) - Yields values from a C-style array, an STL +// ValuesIn(begin,end) container, or an iterator range [begin, end). +// Bool() - Yields sequence {false, true}. +// Combine(g1, g2, ..., gN) - Yields all combinations (the Cartesian product +// for the math savvy) of the values generated +// by the N generators. +// +// For more details, see comments at the definitions of these functions below +// in this file. +// +// The following statement will instantiate tests from the FooTest test case +// each with parameter values "meeny", "miny", and "moe". + +INSTANTIATE_TEST_CASE_P(InstantiationName, + FooTest, + Values("meeny", "miny", "moe")); + +// To distinguish different instances of the pattern, (yes, you +// can instantiate it more then once) the first argument to the +// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the +// actual test case name. Remember to pick unique prefixes for different +// instantiations. The tests from the instantiation above will have +// these names: +// +// * InstantiationName/FooTest.DoesBlah/0 for "meeny" +// * InstantiationName/FooTest.DoesBlah/1 for "miny" +// * InstantiationName/FooTest.DoesBlah/2 for "moe" +// * InstantiationName/FooTest.HasBlahBlah/0 for "meeny" +// * InstantiationName/FooTest.HasBlahBlah/1 for "miny" +// * InstantiationName/FooTest.HasBlahBlah/2 for "moe" +// +// You can use these names in --gtest_filter. +// +// This statement will instantiate all tests from FooTest again, each +// with parameter values "cat" and "dog": + +const char* pets[] = {"cat", "dog"}; +INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets)); + +// The tests from the instantiation above will have these names: +// +// * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat" +// * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog" +// * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat" +// * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog" +// +// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests +// in the given test case, whether their definitions come before or +// AFTER the INSTANTIATE_TEST_CASE_P statement. +// +// Please also note that generator expressions (including parameters to the +// generators) are evaluated in InitGoogleTest(), after main() has started. +// This allows the user on one hand, to adjust generator parameters in order +// to dynamically determine a set of tests to run and on the other hand, +// give the user a chance to inspect the generated tests with Google Test +// reflection API before RUN_ALL_TESTS() is executed. +// +// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc +// for more examples. +// +// In the future, we plan to publish the API for defining new parameter +// generators. But for now this interface remains part of the internal +// implementation and is subject to change. +// +// +// A parameterized test fixture must be derived from testing::Test and from +// testing::WithParamInterface, where T is the type of the parameter +// values. Inheriting from TestWithParam satisfies that requirement because +// TestWithParam inherits from both Test and WithParamInterface. In more +// complicated hierarchies, however, it is occasionally useful to inherit +// separately from Test and WithParamInterface. For example: + +class BaseTest : public ::testing::Test { + // You can inherit all the usual members for a non-parameterized test + // fixture here. +}; + +class DerivedTest : public BaseTest, public ::testing::WithParamInterface { + // The usual test fixture members go here too. +}; + +TEST_F(BaseTest, HasFoo) { + // This is an ordinary non-parameterized test. +} + +TEST_P(DerivedTest, DoesBlah) { + // GetParam works just the same here as if you inherit from TestWithParam. + EXPECT_TRUE(foo.Blah(GetParam())); +} + +#endif // 0 + + +#if !GTEST_OS_SYMBIAN +# include +#endif + +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. +// Copyright 2008 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: vladl@google.com (Vlad Losev) + +// Type and function utilities for implementing parameterized tests. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ + +#include +#include +#include + +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. +// Copyright 2003 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. +// +// Authors: Dan Egnor (egnor@google.com) +// +// A "smart" pointer type with reference tracking. Every pointer to a +// particular object is kept on a circular linked list. When the last pointer +// to an object is destroyed or reassigned, the object is deleted. +// +// Used properly, this deletes the object when the last reference goes away. +// There are several caveats: +// - Like all reference counting schemes, cycles lead to leaks. +// - Each smart pointer is actually two pointers (8 bytes instead of 4). +// - Every time a pointer is assigned, the entire list of pointers to that +// object is traversed. This class is therefore NOT SUITABLE when there +// will often be more than two or three pointers to a particular object. +// - References are only tracked as long as linked_ptr<> objects are copied. +// If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS +// will happen (double deletion). +// +// A good use of this class is storing object references in STL containers. +// You can safely put linked_ptr<> in a vector<>. +// Other uses may not be as good. +// +// Note: If you use an incomplete type with linked_ptr<>, the class +// *containing* linked_ptr<> must have a constructor and destructor (even +// if they do nothing!). +// +// Bill Gibbons suggested we use something like this. +// +// Thread Safety: +// Unlike other linked_ptr implementations, in this implementation +// a linked_ptr object is thread-safe in the sense that: +// - it's safe to copy linked_ptr objects concurrently, +// - it's safe to copy *from* a linked_ptr and read its underlying +// raw pointer (e.g. via get()) concurrently, and +// - it's safe to write to two linked_ptrs that point to the same +// shared object concurrently. +// TODO(wan@google.com): rename this to safe_linked_ptr to avoid +// confusion with normal linked_ptr. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ + +#include +#include + + +namespace testing { +namespace internal { + +// Protects copying of all linked_ptr objects. +GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex); + +// This is used internally by all instances of linked_ptr<>. It needs to be +// a non-template class because different types of linked_ptr<> can refer to +// the same object (linked_ptr(obj) vs linked_ptr(obj)). +// So, it needs to be possible for different types of linked_ptr to participate +// in the same circular linked list, so we need a single class type here. +// +// DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr. +class linked_ptr_internal { + public: + // Create a new circle that includes only this instance. + void join_new() { + next_ = this; + } + + // Many linked_ptr operations may change p.link_ for some linked_ptr + // variable p in the same circle as this object. Therefore we need + // to prevent two such operations from occurring concurrently. + // + // Note that different types of linked_ptr objects can coexist in a + // circle (e.g. linked_ptr, linked_ptr, and + // linked_ptr). Therefore we must use a single mutex to + // protect all linked_ptr objects. This can create serious + // contention in production code, but is acceptable in a testing + // framework. + + // Join an existing circle. + void join(linked_ptr_internal const* ptr) + GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { + MutexLock lock(&g_linked_ptr_mutex); + + linked_ptr_internal const* p = ptr; + while (p->next_ != ptr) p = p->next_; + p->next_ = this; + next_ = ptr; + } + + // Leave whatever circle we're part of. Returns true if we were the + // last member of the circle. Once this is done, you can join() another. + bool depart() + GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { + MutexLock lock(&g_linked_ptr_mutex); + + if (next_ == this) return true; + linked_ptr_internal const* p = next_; + while (p->next_ != this) p = p->next_; + p->next_ = next_; + return false; + } + + private: + mutable linked_ptr_internal const* next_; +}; + +template +class linked_ptr { + public: + typedef T element_type; + + // Take over ownership of a raw pointer. This should happen as soon as + // possible after the object is created. + explicit linked_ptr(T* ptr = NULL) { capture(ptr); } + ~linked_ptr() { depart(); } + + // Copy an existing linked_ptr<>, adding ourselves to the list of references. + template linked_ptr(linked_ptr const& ptr) { copy(&ptr); } + linked_ptr(linked_ptr const& ptr) { // NOLINT + assert(&ptr != this); + copy(&ptr); + } + + // Assignment releases the old value and acquires the new. + template linked_ptr& operator=(linked_ptr const& ptr) { + depart(); + copy(&ptr); + return *this; + } + + linked_ptr& operator=(linked_ptr const& ptr) { + if (&ptr != this) { + depart(); + copy(&ptr); + } + return *this; + } + + // Smart pointer members. + void reset(T* ptr = NULL) { + depart(); + capture(ptr); + } + T* get() const { return value_; } + T* operator->() const { return value_; } + T& operator*() const { return *value_; } + + bool operator==(T* p) const { return value_ == p; } + bool operator!=(T* p) const { return value_ != p; } + template + bool operator==(linked_ptr const& ptr) const { + return value_ == ptr.get(); + } + template + bool operator!=(linked_ptr const& ptr) const { + return value_ != ptr.get(); + } + + private: + template + friend class linked_ptr; + + T* value_; + linked_ptr_internal link_; + + void depart() { + if (link_.depart()) delete value_; + } + + void capture(T* ptr) { + value_ = ptr; + link_.join_new(); + } + + template void copy(linked_ptr const* ptr) { + value_ = ptr->get(); + if (value_) + link_.join(&ptr->link_); + else + link_.join_new(); + } +}; + +template inline +bool operator==(T* ptr, const linked_ptr& x) { + return ptr == x.get(); +} + +template inline +bool operator!=(T* ptr, const linked_ptr& x) { + return ptr != x.get(); +} + +// A function to convert T* into linked_ptr +// Doing e.g. make_linked_ptr(new FooBarBaz(arg)) is a shorter notation +// for linked_ptr >(new FooBarBaz(arg)) +template +linked_ptr make_linked_ptr(T* ptr) { + return linked_ptr(ptr); +} + +} // namespace internal +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Author: wan@google.com (Zhanyong Wan) + +// Google Test - The Google C++ Testing Framework +// +// This file implements a universal value printer that can print a +// value of any type T: +// +// void ::testing::internal::UniversalPrinter::Print(value, ostream_ptr); +// +// A user can teach this function how to print a class type T by +// defining either operator<<() or PrintTo() in the namespace that +// defines T. More specifically, the FIRST defined function in the +// following list will be used (assuming T is defined in namespace +// foo): +// +// 1. foo::PrintTo(const T&, ostream*) +// 2. operator<<(ostream&, const T&) defined in either foo or the +// global namespace. +// +// If none of the above is defined, it will print the debug string of +// the value if it is a protocol buffer, or print the raw bytes in the +// value otherwise. +// +// To aid debugging: when T is a reference type, the address of the +// value is also printed; when T is a (const) char pointer, both the +// pointer value and the NUL-terminated string it points to are +// printed. +// +// We also provide some convenient wrappers: +// +// // Prints a value to a string. For a (const or not) char +// // pointer, the NUL-terminated string (but not the pointer) is +// // printed. +// std::string ::testing::PrintToString(const T& value); +// +// // Prints a value tersely: for a reference type, the referenced +// // value (but not the address) is printed; for a (const or not) char +// // pointer, the NUL-terminated string (but not the pointer) is +// // printed. +// void ::testing::internal::UniversalTersePrint(const T& value, ostream*); +// +// // Prints value using the type inferred by the compiler. The difference +// // from UniversalTersePrint() is that this function prints both the +// // pointer and the NUL-terminated string for a (const or not) char pointer. +// void ::testing::internal::UniversalPrint(const T& value, ostream*); +// +// // Prints the fields of a tuple tersely to a string vector, one +// // element for each field. Tuple support must be enabled in +// // gtest-port.h. +// std::vector UniversalTersePrintTupleFieldsToStrings( +// const Tuple& value); +// +// Known limitation: +// +// The print primitives print the elements of an STL-style container +// using the compiler-inferred type of *iter where iter is a +// const_iterator of the container. When const_iterator is an input +// iterator but not a forward iterator, this inferred type may not +// match value_type, and the print output may be incorrect. In +// practice, this is rarely a problem as for most containers +// const_iterator is a forward iterator. We'll fix this if there's an +// actual need for it. Note that this fix cannot rely on value_type +// being defined as many user-defined container types don't have +// value_type. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ + +#include // NOLINT +#include +#include +#include +#include + +namespace testing { + +// Definitions in the 'internal' and 'internal2' name spaces are +// subject to change without notice. DO NOT USE THEM IN USER CODE! +namespace internal2 { + +// Prints the given number of bytes in the given object to the given +// ostream. +GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes, + size_t count, + ::std::ostream* os); + +// For selecting which printer to use when a given type has neither << +// nor PrintTo(). +enum TypeKind { + kProtobuf, // a protobuf type + kConvertibleToInteger, // a type implicitly convertible to BiggestInt + // (e.g. a named or unnamed enum type) + kOtherType // anything else +}; + +// TypeWithoutFormatter::PrintValue(value, os) is called +// by the universal printer to print a value of type T when neither +// operator<< nor PrintTo() is defined for T, where kTypeKind is the +// "kind" of T as defined by enum TypeKind. +template +class TypeWithoutFormatter { + public: + // This default version is called when kTypeKind is kOtherType. + static void PrintValue(const T& value, ::std::ostream* os) { + PrintBytesInObjectTo(reinterpret_cast(&value), + sizeof(value), os); + } +}; + +// We print a protobuf using its ShortDebugString() when the string +// doesn't exceed this many characters; otherwise we print it using +// DebugString() for better readability. +const size_t kProtobufOneLinerMaxLength = 50; + +template +class TypeWithoutFormatter { + public: + static void PrintValue(const T& value, ::std::ostream* os) { + const ::testing::internal::string short_str = value.ShortDebugString(); + const ::testing::internal::string pretty_str = + short_str.length() <= kProtobufOneLinerMaxLength ? + short_str : ("\n" + value.DebugString()); + *os << ("<" + pretty_str + ">"); + } +}; + +template +class TypeWithoutFormatter { + public: + // Since T has no << operator or PrintTo() but can be implicitly + // converted to BiggestInt, we print it as a BiggestInt. + // + // Most likely T is an enum type (either named or unnamed), in which + // case printing it as an integer is the desired behavior. In case + // T is not an enum, printing it as an integer is the best we can do + // given that it has no user-defined printer. + static void PrintValue(const T& value, ::std::ostream* os) { + const internal::BiggestInt kBigInt = value; + *os << kBigInt; + } +}; + +// Prints the given value to the given ostream. If the value is a +// protocol message, its debug string is printed; if it's an enum or +// of a type implicitly convertible to BiggestInt, it's printed as an +// integer; otherwise the bytes in the value are printed. This is +// what UniversalPrinter::Print() does when it knows nothing about +// type T and T has neither << operator nor PrintTo(). +// +// A user can override this behavior for a class type Foo by defining +// a << operator in the namespace where Foo is defined. +// +// We put this operator in namespace 'internal2' instead of 'internal' +// to simplify the implementation, as much code in 'internal' needs to +// use << in STL, which would conflict with our own << were it defined +// in 'internal'. +// +// Note that this operator<< takes a generic std::basic_ostream type instead of the more restricted std::ostream. If +// we define it to take an std::ostream instead, we'll get an +// "ambiguous overloads" compiler error when trying to print a type +// Foo that supports streaming to std::basic_ostream, as the compiler cannot tell whether +// operator<<(std::ostream&, const T&) or +// operator<<(std::basic_stream, const Foo&) is more +// specific. +template +::std::basic_ostream& operator<<( + ::std::basic_ostream& os, const T& x) { + TypeWithoutFormatter::value ? kProtobuf : + internal::ImplicitlyConvertible::value ? + kConvertibleToInteger : kOtherType)>::PrintValue(x, &os); + return os; +} + +} // namespace internal2 +} // namespace testing + +// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up +// magic needed for implementing UniversalPrinter won't work. +namespace testing_internal { + +// Used to print a value that is not an STL-style container when the +// user doesn't define PrintTo() for it. +template +void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) { + // With the following statement, during unqualified name lookup, + // testing::internal2::operator<< appears as if it was declared in + // the nearest enclosing namespace that contains both + // ::testing_internal and ::testing::internal2, i.e. the global + // namespace. For more details, refer to the C++ Standard section + // 7.3.4-1 [namespace.udir]. This allows us to fall back onto + // testing::internal2::operator<< in case T doesn't come with a << + // operator. + // + // We cannot write 'using ::testing::internal2::operator<<;', which + // gcc 3.3 fails to compile due to a compiler bug. + using namespace ::testing::internal2; // NOLINT + + // Assuming T is defined in namespace foo, in the next statement, + // the compiler will consider all of: + // + // 1. foo::operator<< (thanks to Koenig look-up), + // 2. ::operator<< (as the current namespace is enclosed in ::), + // 3. testing::internal2::operator<< (thanks to the using statement above). + // + // The operator<< whose type matches T best will be picked. + // + // We deliberately allow #2 to be a candidate, as sometimes it's + // impossible to define #1 (e.g. when foo is ::std, defining + // anything in it is undefined behavior unless you are a compiler + // vendor.). + *os << value; +} + +} // namespace testing_internal + +namespace testing { +namespace internal { + +// UniversalPrinter::Print(value, ostream_ptr) prints the given +// value to the given ostream. The caller must ensure that +// 'ostream_ptr' is not NULL, or the behavior is undefined. +// +// We define UniversalPrinter as a class template (as opposed to a +// function template), as we need to partially specialize it for +// reference types, which cannot be done with function templates. +template +class UniversalPrinter; + +template +void UniversalPrint(const T& value, ::std::ostream* os); + +// Used to print an STL-style container when the user doesn't define +// a PrintTo() for it. +template +void DefaultPrintTo(IsContainer /* dummy */, + false_type /* is not a pointer */, + const C& container, ::std::ostream* os) { + const size_t kMaxCount = 32; // The maximum number of elements to print. + *os << '{'; + size_t count = 0; + for (typename C::const_iterator it = container.begin(); + it != container.end(); ++it, ++count) { + if (count > 0) { + *os << ','; + if (count == kMaxCount) { // Enough has been printed. + *os << " ..."; + break; + } + } + *os << ' '; + // We cannot call PrintTo(*it, os) here as PrintTo() doesn't + // handle *it being a native array. + internal::UniversalPrint(*it, os); + } + + if (count > 0) { + *os << ' '; + } + *os << '}'; +} + +// Used to print a pointer that is neither a char pointer nor a member +// pointer, when the user doesn't define PrintTo() for it. (A member +// variable pointer or member function pointer doesn't really point to +// a location in the address space. Their representation is +// implementation-defined. Therefore they will be printed as raw +// bytes.) +template +void DefaultPrintTo(IsNotContainer /* dummy */, + true_type /* is a pointer */, + T* p, ::std::ostream* os) { + if (p == NULL) { + *os << "NULL"; + } else { + // C++ doesn't allow casting from a function pointer to any object + // pointer. + // + // IsTrue() silences warnings: "Condition is always true", + // "unreachable code". + if (IsTrue(ImplicitlyConvertible::value)) { + // T is not a function type. We just call << to print p, + // relying on ADL to pick up user-defined << for their pointer + // types, if any. + *os << p; + } else { + // T is a function type, so '*os << p' doesn't do what we want + // (it just prints p as bool). We want to print p as a const + // void*. However, we cannot cast it to const void* directly, + // even using reinterpret_cast, as earlier versions of gcc + // (e.g. 3.4.5) cannot compile the cast when p is a function + // pointer. Casting to UInt64 first solves the problem. + *os << reinterpret_cast( + reinterpret_cast(p)); + } + } +} + +// Used to print a non-container, non-pointer value when the user +// doesn't define PrintTo() for it. +template +void DefaultPrintTo(IsNotContainer /* dummy */, + false_type /* is not a pointer */, + const T& value, ::std::ostream* os) { + ::testing_internal::DefaultPrintNonContainerTo(value, os); +} + +// Prints the given value using the << operator if it has one; +// otherwise prints the bytes in it. This is what +// UniversalPrinter::Print() does when PrintTo() is not specialized +// or overloaded for type T. +// +// A user can override this behavior for a class type Foo by defining +// an overload of PrintTo() in the namespace where Foo is defined. We +// give the user this option as sometimes defining a << operator for +// Foo is not desirable (e.g. the coding style may prevent doing it, +// or there is already a << operator but it doesn't do what the user +// wants). +template +void PrintTo(const T& value, ::std::ostream* os) { + // DefaultPrintTo() is overloaded. The type of its first two + // arguments determine which version will be picked. If T is an + // STL-style container, the version for container will be called; if + // T is a pointer, the pointer version will be called; otherwise the + // generic version will be called. + // + // Note that we check for container types here, prior to we check + // for protocol message types in our operator<<. The rationale is: + // + // For protocol messages, we want to give people a chance to + // override Google Mock's format by defining a PrintTo() or + // operator<<. For STL containers, other formats can be + // incompatible with Google Mock's format for the container + // elements; therefore we check for container types here to ensure + // that our format is used. + // + // The second argument of DefaultPrintTo() is needed to bypass a bug + // in Symbian's C++ compiler that prevents it from picking the right + // overload between: + // + // PrintTo(const T& x, ...); + // PrintTo(T* x, ...); + DefaultPrintTo(IsContainerTest(0), is_pointer(), value, os); +} + +// The following list of PrintTo() overloads tells +// UniversalPrinter::Print() how to print standard types (built-in +// types, strings, plain arrays, and pointers). + +// Overloads for various char types. +GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os); +GTEST_API_ void PrintTo(signed char c, ::std::ostream* os); +inline void PrintTo(char c, ::std::ostream* os) { + // When printing a plain char, we always treat it as unsigned. This + // way, the output won't be affected by whether the compiler thinks + // char is signed or not. + PrintTo(static_cast(c), os); +} + +// Overloads for other simple built-in types. +inline void PrintTo(bool x, ::std::ostream* os) { + *os << (x ? "true" : "false"); +} + +// Overload for wchar_t type. +// Prints a wchar_t as a symbol if it is printable or as its internal +// code otherwise and also as its decimal code (except for L'\0'). +// The L'\0' char is printed as "L'\\0'". The decimal code is printed +// as signed integer when wchar_t is implemented by the compiler +// as a signed type and is printed as an unsigned integer when wchar_t +// is implemented as an unsigned type. +GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os); + +// Overloads for C strings. +GTEST_API_ void PrintTo(const char* s, ::std::ostream* os); +inline void PrintTo(char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} + +// signed/unsigned char is often used for representing binary data, so +// we print pointers to it as void* to be safe. +inline void PrintTo(const signed char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +inline void PrintTo(signed char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +inline void PrintTo(const unsigned char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +inline void PrintTo(unsigned char* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} + +// MSVC can be configured to define wchar_t as a typedef of unsigned +// short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native +// type. When wchar_t is a typedef, defining an overload for const +// wchar_t* would cause unsigned short* be printed as a wide string, +// possibly causing invalid memory accesses. +#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) +// Overloads for wide C strings +GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os); +inline void PrintTo(wchar_t* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +#endif + +// Overload for C arrays. Multi-dimensional arrays are printed +// properly. + +// Prints the given number of elements in an array, without printing +// the curly braces. +template +void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) { + UniversalPrint(a[0], os); + for (size_t i = 1; i != count; i++) { + *os << ", "; + UniversalPrint(a[i], os); + } +} + +// Overloads for ::string and ::std::string. +#if GTEST_HAS_GLOBAL_STRING +GTEST_API_ void PrintStringTo(const ::string&s, ::std::ostream* os); +inline void PrintTo(const ::string& s, ::std::ostream* os) { + PrintStringTo(s, os); +} +#endif // GTEST_HAS_GLOBAL_STRING + +GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os); +inline void PrintTo(const ::std::string& s, ::std::ostream* os) { + PrintStringTo(s, os); +} + +// Overloads for ::wstring and ::std::wstring. +#if GTEST_HAS_GLOBAL_WSTRING +GTEST_API_ void PrintWideStringTo(const ::wstring&s, ::std::ostream* os); +inline void PrintTo(const ::wstring& s, ::std::ostream* os) { + PrintWideStringTo(s, os); +} +#endif // GTEST_HAS_GLOBAL_WSTRING + +#if GTEST_HAS_STD_WSTRING +GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os); +inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) { + PrintWideStringTo(s, os); +} +#endif // GTEST_HAS_STD_WSTRING + +#if GTEST_HAS_TR1_TUPLE +// Overload for ::std::tr1::tuple. Needed for printing function arguments, +// which are packed as tuples. + +// Helper function for printing a tuple. T must be instantiated with +// a tuple type. +template +void PrintTupleTo(const T& t, ::std::ostream* os); + +// Overloaded PrintTo() for tuples of various arities. We support +// tuples of up-to 10 fields. The following implementation works +// regardless of whether tr1::tuple is implemented using the +// non-standard variadic template feature or not. + +inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo(const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} + +template +void PrintTo( + const ::std::tr1::tuple& t, + ::std::ostream* os) { + PrintTupleTo(t, os); +} +#endif // GTEST_HAS_TR1_TUPLE + +// Overload for std::pair. +template +void PrintTo(const ::std::pair& value, ::std::ostream* os) { + *os << '('; + // We cannot use UniversalPrint(value.first, os) here, as T1 may be + // a reference type. The same for printing value.second. + UniversalPrinter::Print(value.first, os); + *os << ", "; + UniversalPrinter::Print(value.second, os); + *os << ')'; +} + +// Implements printing a non-reference type T by letting the compiler +// pick the right overload of PrintTo() for T. +template +class UniversalPrinter { + public: + // MSVC warns about adding const to a function type, so we want to + // disable the warning. +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4180) // Temporarily disables warning 4180. +#endif // _MSC_VER + + // Note: we deliberately don't call this PrintTo(), as that name + // conflicts with ::testing::internal::PrintTo in the body of the + // function. + static void Print(const T& value, ::std::ostream* os) { + // By default, ::testing::internal::PrintTo() is used for printing + // the value. + // + // Thanks to Koenig look-up, if T is a class and has its own + // PrintTo() function defined in its namespace, that function will + // be visible here. Since it is more specific than the generic ones + // in ::testing::internal, it will be picked by the compiler in the + // following statement - exactly what we want. + PrintTo(value, os); + } + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif // _MSC_VER +}; + +// UniversalPrintArray(begin, len, os) prints an array of 'len' +// elements, starting at address 'begin'. +template +void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) { + if (len == 0) { + *os << "{}"; + } else { + *os << "{ "; + const size_t kThreshold = 18; + const size_t kChunkSize = 8; + // If the array has more than kThreshold elements, we'll have to + // omit some details by printing only the first and the last + // kChunkSize elements. + // TODO(wan@google.com): let the user control the threshold using a flag. + if (len <= kThreshold) { + PrintRawArrayTo(begin, len, os); + } else { + PrintRawArrayTo(begin, kChunkSize, os); + *os << ", ..., "; + PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os); + } + *os << " }"; + } +} +// This overload prints a (const) char array compactly. +GTEST_API_ void UniversalPrintArray( + const char* begin, size_t len, ::std::ostream* os); + +// This overload prints a (const) wchar_t array compactly. +GTEST_API_ void UniversalPrintArray( + const wchar_t* begin, size_t len, ::std::ostream* os); + +// Implements printing an array type T[N]. +template +class UniversalPrinter { + public: + // Prints the given array, omitting some elements when there are too + // many. + static void Print(const T (&a)[N], ::std::ostream* os) { + UniversalPrintArray(a, N, os); + } +}; + +// Implements printing a reference type T&. +template +class UniversalPrinter { + public: + // MSVC warns about adding const to a function type, so we want to + // disable the warning. +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4180) // Temporarily disables warning 4180. +#endif // _MSC_VER + + static void Print(const T& value, ::std::ostream* os) { + // Prints the address of the value. We use reinterpret_cast here + // as static_cast doesn't compile when T is a function type. + *os << "@" << reinterpret_cast(&value) << " "; + + // Then prints the value itself. + UniversalPrint(value, os); + } + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif // _MSC_VER +}; + +// Prints a value tersely: for a reference type, the referenced value +// (but not the address) is printed; for a (const) char pointer, the +// NUL-terminated string (but not the pointer) is printed. + +template +class UniversalTersePrinter { + public: + static void Print(const T& value, ::std::ostream* os) { + UniversalPrint(value, os); + } +}; +template +class UniversalTersePrinter { + public: + static void Print(const T& value, ::std::ostream* os) { + UniversalPrint(value, os); + } +}; +template +class UniversalTersePrinter { + public: + static void Print(const T (&value)[N], ::std::ostream* os) { + UniversalPrinter::Print(value, os); + } +}; +template <> +class UniversalTersePrinter { + public: + static void Print(const char* str, ::std::ostream* os) { + if (str == NULL) { + *os << "NULL"; + } else { + UniversalPrint(string(str), os); + } + } +}; +template <> +class UniversalTersePrinter { + public: + static void Print(char* str, ::std::ostream* os) { + UniversalTersePrinter::Print(str, os); + } +}; + +#if GTEST_HAS_STD_WSTRING +template <> +class UniversalTersePrinter { + public: + static void Print(const wchar_t* str, ::std::ostream* os) { + if (str == NULL) { + *os << "NULL"; + } else { + UniversalPrint(::std::wstring(str), os); + } + } +}; +#endif + +template <> +class UniversalTersePrinter { + public: + static void Print(wchar_t* str, ::std::ostream* os) { + UniversalTersePrinter::Print(str, os); + } +}; + +template +void UniversalTersePrint(const T& value, ::std::ostream* os) { + UniversalTersePrinter::Print(value, os); +} + +// Prints a value using the type inferred by the compiler. The +// difference between this and UniversalTersePrint() is that for a +// (const) char pointer, this prints both the pointer and the +// NUL-terminated string. +template +void UniversalPrint(const T& value, ::std::ostream* os) { + // A workarond for the bug in VC++ 7.1 that prevents us from instantiating + // UniversalPrinter with T directly. + typedef T T1; + UniversalPrinter::Print(value, os); +} + +#if GTEST_HAS_TR1_TUPLE +typedef ::std::vector Strings; + +// This helper template allows PrintTo() for tuples and +// UniversalTersePrintTupleFieldsToStrings() to be defined by +// induction on the number of tuple fields. The idea is that +// TuplePrefixPrinter::PrintPrefixTo(t, os) prints the first N +// fields in tuple t, and can be defined in terms of +// TuplePrefixPrinter. + +// The inductive case. +template +struct TuplePrefixPrinter { + // Prints the first N fields of a tuple. + template + static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) { + TuplePrefixPrinter::PrintPrefixTo(t, os); + *os << ", "; + UniversalPrinter::type> + ::Print(::std::tr1::get(t), os); + } + + // Tersely prints the first N fields of a tuple to a string vector, + // one element for each field. + template + static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) { + TuplePrefixPrinter::TersePrintPrefixToStrings(t, strings); + ::std::stringstream ss; + UniversalTersePrint(::std::tr1::get(t), &ss); + strings->push_back(ss.str()); + } +}; + +// Base cases. +template <> +struct TuplePrefixPrinter<0> { + template + static void PrintPrefixTo(const Tuple&, ::std::ostream*) {} + + template + static void TersePrintPrefixToStrings(const Tuple&, Strings*) {} +}; +// We have to specialize the entire TuplePrefixPrinter<> class +// template here, even though the definition of +// TersePrintPrefixToStrings() is the same as the generic version, as +// Embarcadero (formerly CodeGear, formerly Borland) C++ doesn't +// support specializing a method template of a class template. +template <> +struct TuplePrefixPrinter<1> { + template + static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) { + UniversalPrinter::type>:: + Print(::std::tr1::get<0>(t), os); + } + + template + static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) { + ::std::stringstream ss; + UniversalTersePrint(::std::tr1::get<0>(t), &ss); + strings->push_back(ss.str()); + } +}; + +// Helper function for printing a tuple. T must be instantiated with +// a tuple type. +template +void PrintTupleTo(const T& t, ::std::ostream* os) { + *os << "("; + TuplePrefixPrinter< ::std::tr1::tuple_size::value>:: + PrintPrefixTo(t, os); + *os << ")"; +} + +// Prints the fields of a tuple tersely to a string vector, one +// element for each field. See the comment before +// UniversalTersePrint() for how we define "tersely". +template +Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) { + Strings result; + TuplePrefixPrinter< ::std::tr1::tuple_size::value>:: + TersePrintPrefixToStrings(value, &result); + return result; +} +#endif // GTEST_HAS_TR1_TUPLE + +} // namespace internal + +template +::std::string PrintToString(const T& value) { + ::std::stringstream ss; + internal::UniversalTersePrinter::Print(value, &ss); + return ss.str(); +} + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ + +#if GTEST_HAS_PARAM_TEST + +namespace testing { +namespace internal { + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Outputs a message explaining invalid registration of different +// fixture class for the same test case. This may happen when +// TEST_P macro is used to define two tests with the same name +// but in different namespaces. +GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name, + const char* file, int line); + +template class ParamGeneratorInterface; +template class ParamGenerator; + +// Interface for iterating over elements provided by an implementation +// of ParamGeneratorInterface. +template +class ParamIteratorInterface { + public: + virtual ~ParamIteratorInterface() {} + // A pointer to the base generator instance. + // Used only for the purposes of iterator comparison + // to make sure that two iterators belong to the same generator. + virtual const ParamGeneratorInterface* BaseGenerator() const = 0; + // Advances iterator to point to the next element + // provided by the generator. The caller is responsible + // for not calling Advance() on an iterator equal to + // BaseGenerator()->End(). + virtual void Advance() = 0; + // Clones the iterator object. Used for implementing copy semantics + // of ParamIterator. + virtual ParamIteratorInterface* Clone() const = 0; + // Dereferences the current iterator and provides (read-only) access + // to the pointed value. It is the caller's responsibility not to call + // Current() on an iterator equal to BaseGenerator()->End(). + // Used for implementing ParamGenerator::operator*(). + virtual const T* Current() const = 0; + // Determines whether the given iterator and other point to the same + // element in the sequence generated by the generator. + // Used for implementing ParamGenerator::operator==(). + virtual bool Equals(const ParamIteratorInterface& other) const = 0; +}; + +// Class iterating over elements provided by an implementation of +// ParamGeneratorInterface. It wraps ParamIteratorInterface +// and implements the const forward iterator concept. +template +class ParamIterator { + public: + typedef T value_type; + typedef const T& reference; + typedef ptrdiff_t difference_type; + + // ParamIterator assumes ownership of the impl_ pointer. + ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {} + ParamIterator& operator=(const ParamIterator& other) { + if (this != &other) + impl_.reset(other.impl_->Clone()); + return *this; + } + + const T& operator*() const { return *impl_->Current(); } + const T* operator->() const { return impl_->Current(); } + // Prefix version of operator++. + ParamIterator& operator++() { + impl_->Advance(); + return *this; + } + // Postfix version of operator++. + ParamIterator operator++(int /*unused*/) { + ParamIteratorInterface* clone = impl_->Clone(); + impl_->Advance(); + return ParamIterator(clone); + } + bool operator==(const ParamIterator& other) const { + return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_); + } + bool operator!=(const ParamIterator& other) const { + return !(*this == other); + } + + private: + friend class ParamGenerator; + explicit ParamIterator(ParamIteratorInterface* impl) : impl_(impl) {} + scoped_ptr > impl_; +}; + +// ParamGeneratorInterface is the binary interface to access generators +// defined in other translation units. +template +class ParamGeneratorInterface { + public: + typedef T ParamType; + + virtual ~ParamGeneratorInterface() {} + + // Generator interface definition + virtual ParamIteratorInterface* Begin() const = 0; + virtual ParamIteratorInterface* End() const = 0; +}; + +// Wraps ParamGeneratorInterface and provides general generator syntax +// compatible with the STL Container concept. +// This class implements copy initialization semantics and the contained +// ParamGeneratorInterface instance is shared among all copies +// of the original object. This is possible because that instance is immutable. +template +class ParamGenerator { + public: + typedef ParamIterator iterator; + + explicit ParamGenerator(ParamGeneratorInterface* impl) : impl_(impl) {} + ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {} + + ParamGenerator& operator=(const ParamGenerator& other) { + impl_ = other.impl_; + return *this; + } + + iterator begin() const { return iterator(impl_->Begin()); } + iterator end() const { return iterator(impl_->End()); } + + private: + linked_ptr > impl_; +}; + +// Generates values from a range of two comparable values. Can be used to +// generate sequences of user-defined types that implement operator+() and +// operator<(). +// This class is used in the Range() function. +template +class RangeGenerator : public ParamGeneratorInterface { + public: + RangeGenerator(T begin, T end, IncrementT step) + : begin_(begin), end_(end), + step_(step), end_index_(CalculateEndIndex(begin, end, step)) {} + virtual ~RangeGenerator() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, begin_, 0, step_); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, end_, end_index_, step_); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, T value, int index, + IncrementT step) + : base_(base), value_(value), index_(index), step_(step) {} + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + virtual void Advance() { + value_ = value_ + step_; + index_++; + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const T* Current() const { return &value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const int other_index = + CheckedDowncastToActualType(&other)->index_; + return index_ == other_index; + } + + private: + Iterator(const Iterator& other) + : ParamIteratorInterface(), + base_(other.base_), value_(other.value_), index_(other.index_), + step_(other.step_) {} + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + T value_; + int index_; + const IncrementT step_; + }; // class RangeGenerator::Iterator + + static int CalculateEndIndex(const T& begin, + const T& end, + const IncrementT& step) { + int end_index = 0; + for (T i = begin; i < end; i = i + step) + end_index++; + return end_index; + } + + // No implementation - assignment is unsupported. + void operator=(const RangeGenerator& other); + + const T begin_; + const T end_; + const IncrementT step_; + // The index for the end() iterator. All the elements in the generated + // sequence are indexed (0-based) to aid iterator comparison. + const int end_index_; +}; // class RangeGenerator + + +// Generates values from a pair of STL-style iterators. Used in the +// ValuesIn() function. The elements are copied from the source range +// since the source can be located on the stack, and the generator +// is likely to persist beyond that stack frame. +template +class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface { + public: + template + ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end) + : container_(begin, end) {} + virtual ~ValuesInIteratorRangeGenerator() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, container_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, container_.end()); + } + + private: + typedef typename ::std::vector ContainerType; + + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + typename ContainerType::const_iterator iterator) + : base_(base), iterator_(iterator) {} + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + virtual void Advance() { + ++iterator_; + value_.reset(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + // We need to use cached value referenced by iterator_ because *iterator_ + // can return a temporary object (and of type other then T), so just + // having "return &*iterator_;" doesn't work. + // value_ is updated here and not in Advance() because Advance() + // can advance iterator_ beyond the end of the range, and we cannot + // detect that fact. The client code, on the other hand, is + // responsible for not calling Current() on an out-of-range iterator. + virtual const T* Current() const { + if (value_.get() == NULL) + value_.reset(new T(*iterator_)); + return value_.get(); + } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + return iterator_ == + CheckedDowncastToActualType(&other)->iterator_; + } + + private: + Iterator(const Iterator& other) + // The explicit constructor call suppresses a false warning + // emitted by gcc when supplied with the -Wextra option. + : ParamIteratorInterface(), + base_(other.base_), + iterator_(other.iterator_) {} + + const ParamGeneratorInterface* const base_; + typename ContainerType::const_iterator iterator_; + // A cached value of *iterator_. We keep it here to allow access by + // pointer in the wrapping iterator's operator->(). + // value_ needs to be mutable to be accessed in Current(). + // Use of scoped_ptr helps manage cached value's lifetime, + // which is bound by the lifespan of the iterator itself. + mutable scoped_ptr value_; + }; // class ValuesInIteratorRangeGenerator::Iterator + + // No implementation - assignment is unsupported. + void operator=(const ValuesInIteratorRangeGenerator& other); + + const ContainerType container_; +}; // class ValuesInIteratorRangeGenerator + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Stores a parameter value and later creates tests parameterized with that +// value. +template +class ParameterizedTestFactory : public TestFactoryBase { + public: + typedef typename TestClass::ParamType ParamType; + explicit ParameterizedTestFactory(ParamType parameter) : + parameter_(parameter) {} + virtual Test* CreateTest() { + TestClass::SetParam(¶meter_); + return new TestClass(); + } + + private: + const ParamType parameter_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory); +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// TestMetaFactoryBase is a base class for meta-factories that create +// test factories for passing into MakeAndRegisterTestInfo function. +template +class TestMetaFactoryBase { + public: + virtual ~TestMetaFactoryBase() {} + + virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0; +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// TestMetaFactory creates test factories for passing into +// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives +// ownership of test factory pointer, same factory object cannot be passed +// into that method twice. But ParameterizedTestCaseInfo is going to call +// it for each Test/Parameter value combination. Thus it needs meta factory +// creator class. +template +class TestMetaFactory + : public TestMetaFactoryBase { + public: + typedef typename TestCase::ParamType ParamType; + + TestMetaFactory() {} + + virtual TestFactoryBase* CreateTestFactory(ParamType parameter) { + return new ParameterizedTestFactory(parameter); + } + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory); +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// ParameterizedTestCaseInfoBase is a generic interface +// to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase +// accumulates test information provided by TEST_P macro invocations +// and generators provided by INSTANTIATE_TEST_CASE_P macro invocations +// and uses that information to register all resulting test instances +// in RegisterTests method. The ParameterizeTestCaseRegistry class holds +// a collection of pointers to the ParameterizedTestCaseInfo objects +// and calls RegisterTests() on each of them when asked. +class ParameterizedTestCaseInfoBase { + public: + virtual ~ParameterizedTestCaseInfoBase() {} + + // Base part of test case name for display purposes. + virtual const string& GetTestCaseName() const = 0; + // Test case id to verify identity. + virtual TypeId GetTestCaseTypeId() const = 0; + // UnitTest class invokes this method to register tests in this + // test case right before running them in RUN_ALL_TESTS macro. + // This method should not be called more then once on any single + // instance of a ParameterizedTestCaseInfoBase derived class. + virtual void RegisterTests() = 0; + + protected: + ParameterizedTestCaseInfoBase() {} + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase); +}; + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// ParameterizedTestCaseInfo accumulates tests obtained from TEST_P +// macro invocations for a particular test case and generators +// obtained from INSTANTIATE_TEST_CASE_P macro invocations for that +// test case. It registers tests with all values generated by all +// generators when asked. +template +class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { + public: + // ParamType and GeneratorCreationFunc are private types but are required + // for declarations of public methods AddTestPattern() and + // AddTestCaseInstantiation(). + typedef typename TestCase::ParamType ParamType; + // A function that returns an instance of appropriate generator type. + typedef ParamGenerator(GeneratorCreationFunc)(); + + explicit ParameterizedTestCaseInfo(const char* name) + : test_case_name_(name) {} + + // Test case base name for display purposes. + virtual const string& GetTestCaseName() const { return test_case_name_; } + // Test case id to verify identity. + virtual TypeId GetTestCaseTypeId() const { return GetTypeId(); } + // TEST_P macro uses AddTestPattern() to record information + // about a single test in a LocalTestInfo structure. + // test_case_name is the base name of the test case (without invocation + // prefix). test_base_name is the name of an individual test without + // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is + // test case base name and DoBar is test base name. + void AddTestPattern(const char* test_case_name, + const char* test_base_name, + TestMetaFactoryBase* meta_factory) { + tests_.push_back(linked_ptr(new TestInfo(test_case_name, + test_base_name, + meta_factory))); + } + // INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information + // about a generator. + int AddTestCaseInstantiation(const string& instantiation_name, + GeneratorCreationFunc* func, + const char* /* file */, + int /* line */) { + instantiations_.push_back(::std::make_pair(instantiation_name, func)); + return 0; // Return value used only to run this method in namespace scope. + } + // UnitTest class invokes this method to register tests in this test case + // test cases right before running tests in RUN_ALL_TESTS macro. + // This method should not be called more then once on any single + // instance of a ParameterizedTestCaseInfoBase derived class. + // UnitTest has a guard to prevent from calling this method more then once. + virtual void RegisterTests() { + for (typename TestInfoContainer::iterator test_it = tests_.begin(); + test_it != tests_.end(); ++test_it) { + linked_ptr test_info = *test_it; + for (typename InstantiationContainer::iterator gen_it = + instantiations_.begin(); gen_it != instantiations_.end(); + ++gen_it) { + const string& instantiation_name = gen_it->first; + ParamGenerator generator((*gen_it->second)()); + + string test_case_name; + if ( !instantiation_name.empty() ) + test_case_name = instantiation_name + "/"; + test_case_name += test_info->test_case_base_name; + + int i = 0; + for (typename ParamGenerator::iterator param_it = + generator.begin(); + param_it != generator.end(); ++param_it, ++i) { + Message test_name_stream; + test_name_stream << test_info->test_base_name << "/" << i; + MakeAndRegisterTestInfo( + test_case_name.c_str(), + test_name_stream.GetString().c_str(), + NULL, // No type parameter. + PrintToString(*param_it).c_str(), + GetTestCaseTypeId(), + TestCase::SetUpTestCase, + TestCase::TearDownTestCase, + test_info->test_meta_factory->CreateTestFactory(*param_it)); + } // for param_it + } // for gen_it + } // for test_it + } // RegisterTests + + private: + // LocalTestInfo structure keeps information about a single test registered + // with TEST_P macro. + struct TestInfo { + TestInfo(const char* a_test_case_base_name, + const char* a_test_base_name, + TestMetaFactoryBase* a_test_meta_factory) : + test_case_base_name(a_test_case_base_name), + test_base_name(a_test_base_name), + test_meta_factory(a_test_meta_factory) {} + + const string test_case_base_name; + const string test_base_name; + const scoped_ptr > test_meta_factory; + }; + typedef ::std::vector > TestInfoContainer; + // Keeps pairs of + // received from INSTANTIATE_TEST_CASE_P macros. + typedef ::std::vector > + InstantiationContainer; + + const string test_case_name_; + TestInfoContainer tests_; + InstantiationContainer instantiations_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo); +}; // class ParameterizedTestCaseInfo + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// ParameterizedTestCaseRegistry contains a map of ParameterizedTestCaseInfoBase +// classes accessed by test case names. TEST_P and INSTANTIATE_TEST_CASE_P +// macros use it to locate their corresponding ParameterizedTestCaseInfo +// descriptors. +class ParameterizedTestCaseRegistry { + public: + ParameterizedTestCaseRegistry() {} + ~ParameterizedTestCaseRegistry() { + for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); + it != test_case_infos_.end(); ++it) { + delete *it; + } + } + + // Looks up or creates and returns a structure containing information about + // tests and instantiations of a particular test case. + template + ParameterizedTestCaseInfo* GetTestCasePatternHolder( + const char* test_case_name, + const char* file, + int line) { + ParameterizedTestCaseInfo* typed_test_info = NULL; + for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); + it != test_case_infos_.end(); ++it) { + if ((*it)->GetTestCaseName() == test_case_name) { + if ((*it)->GetTestCaseTypeId() != GetTypeId()) { + // Complain about incorrect usage of Google Test facilities + // and terminate the program since we cannot guaranty correct + // test case setup and tear-down in this case. + ReportInvalidTestCaseType(test_case_name, file, line); + posix::Abort(); + } else { + // At this point we are sure that the object we found is of the same + // type we are looking for, so we downcast it to that type + // without further checks. + typed_test_info = CheckedDowncastToActualType< + ParameterizedTestCaseInfo >(*it); + } + break; + } + } + if (typed_test_info == NULL) { + typed_test_info = new ParameterizedTestCaseInfo(test_case_name); + test_case_infos_.push_back(typed_test_info); + } + return typed_test_info; + } + void RegisterTests() { + for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); + it != test_case_infos_.end(); ++it) { + (*it)->RegisterTests(); + } + } + + private: + typedef ::std::vector TestCaseInfoContainer; + + TestCaseInfoContainer test_case_infos_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry); +}; + +} // namespace internal +} // namespace testing + +#endif // GTEST_HAS_PARAM_TEST + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ +// This file was GENERATED by command: +// pump.py gtest-param-util-generated.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2008 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: vladl@google.com (Vlad Losev) + +// Type and function utilities for implementing parameterized tests. +// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! +// +// Currently Google Test supports at most 50 arguments in Values, +// and at most 10 arguments in Combine. Please contact +// googletestframework@googlegroups.com if you need more. +// Please note that the number of arguments to Combine is limited +// by the maximum arity of the implementation of tr1::tuple which is +// currently set at 10. + +#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ +#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ + +// scripts/fuse_gtest.py depends on gtest's own header being #included +// *unconditionally*. Therefore these #includes cannot be moved +// inside #if GTEST_HAS_PARAM_TEST. + +#if GTEST_HAS_PARAM_TEST + +namespace testing { + +// Forward declarations of ValuesIn(), which is implemented in +// include/gtest/gtest-param-test.h. +template +internal::ParamGenerator< + typename ::testing::internal::IteratorTraits::value_type> +ValuesIn(ForwardIterator begin, ForwardIterator end); + +template +internal::ParamGenerator ValuesIn(const T (&array)[N]); + +template +internal::ParamGenerator ValuesIn( + const Container& container); + +namespace internal { + +// Used in the Values() function to provide polymorphic capabilities. +template +class ValueArray1 { + public: + explicit ValueArray1(T1 v1) : v1_(v1) {} + + template + operator ParamGenerator() const { return ValuesIn(&v1_, &v1_ + 1); } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray1& other); + + const T1 v1_; +}; + +template +class ValueArray2 { + public: + ValueArray2(T1 v1, T2 v2) : v1_(v1), v2_(v2) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray2& other); + + const T1 v1_; + const T2 v2_; +}; + +template +class ValueArray3 { + public: + ValueArray3(T1 v1, T2 v2, T3 v3) : v1_(v1), v2_(v2), v3_(v3) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray3& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; +}; + +template +class ValueArray4 { + public: + ValueArray4(T1 v1, T2 v2, T3 v3, T4 v4) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray4& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; +}; + +template +class ValueArray5 { + public: + ValueArray5(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray5& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; +}; + +template +class ValueArray6 { + public: + ValueArray6(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray6& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; +}; + +template +class ValueArray7 { + public: + ValueArray7(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray7& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; +}; + +template +class ValueArray8 { + public: + ValueArray8(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray8& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; +}; + +template +class ValueArray9 { + public: + ValueArray9(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray9& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; +}; + +template +class ValueArray10 { + public: + ValueArray10(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray10& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; +}; + +template +class ValueArray11 { + public: + ValueArray11(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray11& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; +}; + +template +class ValueArray12 { + public: + ValueArray12(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray12& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; +}; + +template +class ValueArray13 { + public: + ValueArray13(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray13& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; +}; + +template +class ValueArray14 { + public: + ValueArray14(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray14& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; +}; + +template +class ValueArray15 { + public: + ValueArray15(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray15& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; +}; + +template +class ValueArray16 { + public: + ValueArray16(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray16& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; +}; + +template +class ValueArray17 { + public: + ValueArray17(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, + T17 v17) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray17& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; +}; + +template +class ValueArray18 { + public: + ValueArray18(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray18& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; +}; + +template +class ValueArray19 { + public: + ValueArray19(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray19& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; +}; + +template +class ValueArray20 { + public: + ValueArray20(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray20& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; +}; + +template +class ValueArray21 { + public: + ValueArray21(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray21& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; +}; + +template +class ValueArray22 { + public: + ValueArray22(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray22& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; +}; + +template +class ValueArray23 { + public: + ValueArray23(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray23& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; +}; + +template +class ValueArray24 { + public: + ValueArray24(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray24& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; +}; + +template +class ValueArray25 { + public: + ValueArray25(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, + T25 v25) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray25& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; +}; + +template +class ValueArray26 { + public: + ValueArray26(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray26& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; +}; + +template +class ValueArray27 { + public: + ValueArray27(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), + v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), + v26_(v26), v27_(v27) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray27& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; +}; + +template +class ValueArray28 { + public: + ValueArray28(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), + v25_(v25), v26_(v26), v27_(v27), v28_(v28) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray28& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; +}; + +template +class ValueArray29 { + public: + ValueArray29(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), + v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray29& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; +}; + +template +class ValueArray30 { + public: + ValueArray30(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray30& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; +}; + +template +class ValueArray31 { + public: + ValueArray31(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray31& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; +}; + +template +class ValueArray32 { + public: + ValueArray32(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), + v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray32& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; +}; + +template +class ValueArray33 { + public: + ValueArray33(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, + T33 v33) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray33& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; +}; + +template +class ValueArray34 { + public: + ValueArray34(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray34& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; +}; + +template +class ValueArray35 { + public: + ValueArray35(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), + v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), + v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), + v32_(v32), v33_(v33), v34_(v34), v35_(v35) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray35& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; +}; + +template +class ValueArray36 { + public: + ValueArray36(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), + v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), + v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray36& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; +}; + +template +class ValueArray37 { + public: + ValueArray37(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), + v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), + v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), + v36_(v36), v37_(v37) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray37& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; +}; + +template +class ValueArray38 { + public: + ValueArray38(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray38& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; +}; + +template +class ValueArray39 { + public: + ValueArray39(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray39& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; +}; + +template +class ValueArray40 { + public: + ValueArray40(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), + v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), + v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), + v40_(v40) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray40& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; +}; + +template +class ValueArray41 { + public: + ValueArray41(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, + T41 v41) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray41& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; +}; + +template +class ValueArray42 { + public: + ValueArray42(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41), v42_(v42) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray42& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; +}; + +template +class ValueArray43 { + public: + ValueArray43(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), + v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), + v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), + v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), + v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), + v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), + v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray43& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; +}; + +template +class ValueArray44 { + public: + ValueArray44(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), + v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), + v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), + v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), + v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), + v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), + v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), + v43_(v43), v44_(v44) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray44& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; +}; + +template +class ValueArray45 { + public: + ValueArray45(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), + v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), + v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), + v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), + v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), + v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), + v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), + v42_(v42), v43_(v43), v44_(v44), v45_(v45) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray45& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; +}; + +template +class ValueArray46 { + public: + ValueArray46(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) : v1_(v1), v2_(v2), v3_(v3), + v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), + v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray46& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; +}; + +template +class ValueArray47 { + public: + ValueArray47(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) : v1_(v1), v2_(v2), + v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), + v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), + v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), + v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), + v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), + v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), + v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46), + v47_(v47) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_), static_cast(v47_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray47& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; +}; + +template +class ValueArray48 { + public: + ValueArray48(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48) : v1_(v1), + v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), + v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), + v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), + v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), + v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), + v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), + v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), + v46_(v46), v47_(v47), v48_(v48) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_), static_cast(v47_), + static_cast(v48_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray48& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; + const T48 v48_; +}; + +template +class ValueArray49 { + public: + ValueArray49(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, + T49 v49) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), + v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_), static_cast(v47_), + static_cast(v48_), static_cast(v49_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray49& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; + const T48 v48_; + const T49 v49_; +}; + +template +class ValueArray50 { + public: + ValueArray50(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, T49 v49, + T50 v50) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), + v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), + v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), + v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), + v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), + v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), + v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), + v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49), v50_(v50) {} + + template + operator ParamGenerator() const { + const T array[] = {static_cast(v1_), static_cast(v2_), + static_cast(v3_), static_cast(v4_), static_cast(v5_), + static_cast(v6_), static_cast(v7_), static_cast(v8_), + static_cast(v9_), static_cast(v10_), static_cast(v11_), + static_cast(v12_), static_cast(v13_), static_cast(v14_), + static_cast(v15_), static_cast(v16_), static_cast(v17_), + static_cast(v18_), static_cast(v19_), static_cast(v20_), + static_cast(v21_), static_cast(v22_), static_cast(v23_), + static_cast(v24_), static_cast(v25_), static_cast(v26_), + static_cast(v27_), static_cast(v28_), static_cast(v29_), + static_cast(v30_), static_cast(v31_), static_cast(v32_), + static_cast(v33_), static_cast(v34_), static_cast(v35_), + static_cast(v36_), static_cast(v37_), static_cast(v38_), + static_cast(v39_), static_cast(v40_), static_cast(v41_), + static_cast(v42_), static_cast(v43_), static_cast(v44_), + static_cast(v45_), static_cast(v46_), static_cast(v47_), + static_cast(v48_), static_cast(v49_), static_cast(v50_)}; + return ValuesIn(array); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const ValueArray50& other); + + const T1 v1_; + const T2 v2_; + const T3 v3_; + const T4 v4_; + const T5 v5_; + const T6 v6_; + const T7 v7_; + const T8 v8_; + const T9 v9_; + const T10 v10_; + const T11 v11_; + const T12 v12_; + const T13 v13_; + const T14 v14_; + const T15 v15_; + const T16 v16_; + const T17 v17_; + const T18 v18_; + const T19 v19_; + const T20 v20_; + const T21 v21_; + const T22 v22_; + const T23 v23_; + const T24 v24_; + const T25 v25_; + const T26 v26_; + const T27 v27_; + const T28 v28_; + const T29 v29_; + const T30 v30_; + const T31 v31_; + const T32 v32_; + const T33 v33_; + const T34 v34_; + const T35 v35_; + const T36 v36_; + const T37 v37_; + const T38 v38_; + const T39 v39_; + const T40 v40_; + const T41 v41_; + const T42 v42_; + const T43 v43_; + const T44 v44_; + const T45 v45_; + const T46 v46_; + const T47 v47_; + const T48 v48_; + const T49 v49_; + const T50 v50_; +}; + +# if GTEST_HAS_COMBINE +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Generates values from the Cartesian product of values produced +// by the argument generators. +// +template +class CartesianProductGenerator2 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator2(const ParamGenerator& g1, + const ParamGenerator& g2) + : g1_(g1), g2_(g2) {} + virtual ~CartesianProductGenerator2() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current2_; + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + ParamType current_value_; + }; // class CartesianProductGenerator2::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator2& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; +}; // class CartesianProductGenerator2 + + +template +class CartesianProductGenerator3 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator3(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3) + : g1_(g1), g2_(g2), g3_(g3) {} + virtual ~CartesianProductGenerator3() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current3_; + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + ParamType current_value_; + }; // class CartesianProductGenerator3::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator3& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; +}; // class CartesianProductGenerator3 + + +template +class CartesianProductGenerator4 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator4(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {} + virtual ~CartesianProductGenerator4() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current4_; + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + ParamType current_value_; + }; // class CartesianProductGenerator4::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator4& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; +}; // class CartesianProductGenerator4 + + +template +class CartesianProductGenerator5 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator5(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {} + virtual ~CartesianProductGenerator5() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current5_; + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + ParamType current_value_; + }; // class CartesianProductGenerator5::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator5& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; +}; // class CartesianProductGenerator5 + + +template +class CartesianProductGenerator6 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator6(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {} + virtual ~CartesianProductGenerator6() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current6_; + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + ParamType current_value_; + }; // class CartesianProductGenerator6::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator6& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; +}; // class CartesianProductGenerator6 + + +template +class CartesianProductGenerator7 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator7(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {} + virtual ~CartesianProductGenerator7() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current7_; + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + ParamType current_value_; + }; // class CartesianProductGenerator7::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator7& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; +}; // class CartesianProductGenerator7 + + +template +class CartesianProductGenerator8 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator8(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7, + const ParamGenerator& g8) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), + g8_(g8) {} + virtual ~CartesianProductGenerator8() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin(), g8_, g8_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, + g8_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7, + const ParamGenerator& g8, + const typename ParamGenerator::iterator& current8) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7), + begin8_(g8.begin()), end8_(g8.end()), current8_(current8) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current8_; + if (current8_ == end8_) { + current8_ = begin8_; + ++current7_; + } + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_ && + current8_ == typed_other->current8_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_), + begin8_(other.begin8_), + end8_(other.end8_), + current8_(other.current8_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_, *current8_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_ || + current8_ == end8_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + const typename ParamGenerator::iterator begin8_; + const typename ParamGenerator::iterator end8_; + typename ParamGenerator::iterator current8_; + ParamType current_value_; + }; // class CartesianProductGenerator8::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator8& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; + const ParamGenerator g8_; +}; // class CartesianProductGenerator8 + + +template +class CartesianProductGenerator9 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator9(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7, + const ParamGenerator& g8, const ParamGenerator& g9) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9) {} + virtual ~CartesianProductGenerator9() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, + g8_.end(), g9_, g9_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7, + const ParamGenerator& g8, + const typename ParamGenerator::iterator& current8, + const ParamGenerator& g9, + const typename ParamGenerator::iterator& current9) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7), + begin8_(g8.begin()), end8_(g8.end()), current8_(current8), + begin9_(g9.begin()), end9_(g9.end()), current9_(current9) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current9_; + if (current9_ == end9_) { + current9_ = begin9_; + ++current8_; + } + if (current8_ == end8_) { + current8_ = begin8_; + ++current7_; + } + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_ && + current8_ == typed_other->current8_ && + current9_ == typed_other->current9_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_), + begin8_(other.begin8_), + end8_(other.end8_), + current8_(other.current8_), + begin9_(other.begin9_), + end9_(other.end9_), + current9_(other.current9_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_, *current8_, + *current9_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_ || + current8_ == end8_ || + current9_ == end9_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + const typename ParamGenerator::iterator begin8_; + const typename ParamGenerator::iterator end8_; + typename ParamGenerator::iterator current8_; + const typename ParamGenerator::iterator begin9_; + const typename ParamGenerator::iterator end9_; + typename ParamGenerator::iterator current9_; + ParamType current_value_; + }; // class CartesianProductGenerator9::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator9& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; + const ParamGenerator g8_; + const ParamGenerator g9_; +}; // class CartesianProductGenerator9 + + +template +class CartesianProductGenerator10 + : public ParamGeneratorInterface< ::std::tr1::tuple > { + public: + typedef ::std::tr1::tuple ParamType; + + CartesianProductGenerator10(const ParamGenerator& g1, + const ParamGenerator& g2, const ParamGenerator& g3, + const ParamGenerator& g4, const ParamGenerator& g5, + const ParamGenerator& g6, const ParamGenerator& g7, + const ParamGenerator& g8, const ParamGenerator& g9, + const ParamGenerator& g10) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9), g10_(g10) {} + virtual ~CartesianProductGenerator10() {} + + virtual ParamIteratorInterface* Begin() const { + return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, + g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, + g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin(), g10_, g10_.begin()); + } + virtual ParamIteratorInterface* End() const { + return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), + g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, + g8_.end(), g9_, g9_.end(), g10_, g10_.end()); + } + + private: + class Iterator : public ParamIteratorInterface { + public: + Iterator(const ParamGeneratorInterface* base, + const ParamGenerator& g1, + const typename ParamGenerator::iterator& current1, + const ParamGenerator& g2, + const typename ParamGenerator::iterator& current2, + const ParamGenerator& g3, + const typename ParamGenerator::iterator& current3, + const ParamGenerator& g4, + const typename ParamGenerator::iterator& current4, + const ParamGenerator& g5, + const typename ParamGenerator::iterator& current5, + const ParamGenerator& g6, + const typename ParamGenerator::iterator& current6, + const ParamGenerator& g7, + const typename ParamGenerator::iterator& current7, + const ParamGenerator& g8, + const typename ParamGenerator::iterator& current8, + const ParamGenerator& g9, + const typename ParamGenerator::iterator& current9, + const ParamGenerator& g10, + const typename ParamGenerator::iterator& current10) + : base_(base), + begin1_(g1.begin()), end1_(g1.end()), current1_(current1), + begin2_(g2.begin()), end2_(g2.end()), current2_(current2), + begin3_(g3.begin()), end3_(g3.end()), current3_(current3), + begin4_(g4.begin()), end4_(g4.end()), current4_(current4), + begin5_(g5.begin()), end5_(g5.end()), current5_(current5), + begin6_(g6.begin()), end6_(g6.end()), current6_(current6), + begin7_(g7.begin()), end7_(g7.end()), current7_(current7), + begin8_(g8.begin()), end8_(g8.end()), current8_(current8), + begin9_(g9.begin()), end9_(g9.end()), current9_(current9), + begin10_(g10.begin()), end10_(g10.end()), current10_(current10) { + ComputeCurrentValue(); + } + virtual ~Iterator() {} + + virtual const ParamGeneratorInterface* BaseGenerator() const { + return base_; + } + // Advance should not be called on beyond-of-range iterators + // so no component iterators must be beyond end of range, either. + virtual void Advance() { + assert(!AtEnd()); + ++current10_; + if (current10_ == end10_) { + current10_ = begin10_; + ++current9_; + } + if (current9_ == end9_) { + current9_ = begin9_; + ++current8_; + } + if (current8_ == end8_) { + current8_ = begin8_; + ++current7_; + } + if (current7_ == end7_) { + current7_ = begin7_; + ++current6_; + } + if (current6_ == end6_) { + current6_ = begin6_; + ++current5_; + } + if (current5_ == end5_) { + current5_ = begin5_; + ++current4_; + } + if (current4_ == end4_) { + current4_ = begin4_; + ++current3_; + } + if (current3_ == end3_) { + current3_ = begin3_; + ++current2_; + } + if (current2_ == end2_) { + current2_ = begin2_; + ++current1_; + } + ComputeCurrentValue(); + } + virtual ParamIteratorInterface* Clone() const { + return new Iterator(*this); + } + virtual const ParamType* Current() const { return ¤t_value_; } + virtual bool Equals(const ParamIteratorInterface& other) const { + // Having the same base generator guarantees that the other + // iterator is of the same type and we can downcast. + GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) + << "The program attempted to compare iterators " + << "from different generators." << std::endl; + const Iterator* typed_other = + CheckedDowncastToActualType(&other); + // We must report iterators equal if they both point beyond their + // respective ranges. That can happen in a variety of fashions, + // so we have to consult AtEnd(). + return (AtEnd() && typed_other->AtEnd()) || + ( + current1_ == typed_other->current1_ && + current2_ == typed_other->current2_ && + current3_ == typed_other->current3_ && + current4_ == typed_other->current4_ && + current5_ == typed_other->current5_ && + current6_ == typed_other->current6_ && + current7_ == typed_other->current7_ && + current8_ == typed_other->current8_ && + current9_ == typed_other->current9_ && + current10_ == typed_other->current10_); + } + + private: + Iterator(const Iterator& other) + : base_(other.base_), + begin1_(other.begin1_), + end1_(other.end1_), + current1_(other.current1_), + begin2_(other.begin2_), + end2_(other.end2_), + current2_(other.current2_), + begin3_(other.begin3_), + end3_(other.end3_), + current3_(other.current3_), + begin4_(other.begin4_), + end4_(other.end4_), + current4_(other.current4_), + begin5_(other.begin5_), + end5_(other.end5_), + current5_(other.current5_), + begin6_(other.begin6_), + end6_(other.end6_), + current6_(other.current6_), + begin7_(other.begin7_), + end7_(other.end7_), + current7_(other.current7_), + begin8_(other.begin8_), + end8_(other.end8_), + current8_(other.current8_), + begin9_(other.begin9_), + end9_(other.end9_), + current9_(other.current9_), + begin10_(other.begin10_), + end10_(other.end10_), + current10_(other.current10_) { + ComputeCurrentValue(); + } + + void ComputeCurrentValue() { + if (!AtEnd()) + current_value_ = ParamType(*current1_, *current2_, *current3_, + *current4_, *current5_, *current6_, *current7_, *current8_, + *current9_, *current10_); + } + bool AtEnd() const { + // We must report iterator past the end of the range when either of the + // component iterators has reached the end of its range. + return + current1_ == end1_ || + current2_ == end2_ || + current3_ == end3_ || + current4_ == end4_ || + current5_ == end5_ || + current6_ == end6_ || + current7_ == end7_ || + current8_ == end8_ || + current9_ == end9_ || + current10_ == end10_; + } + + // No implementation - assignment is unsupported. + void operator=(const Iterator& other); + + const ParamGeneratorInterface* const base_; + // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. + // current[i]_ is the actual traversing iterator. + const typename ParamGenerator::iterator begin1_; + const typename ParamGenerator::iterator end1_; + typename ParamGenerator::iterator current1_; + const typename ParamGenerator::iterator begin2_; + const typename ParamGenerator::iterator end2_; + typename ParamGenerator::iterator current2_; + const typename ParamGenerator::iterator begin3_; + const typename ParamGenerator::iterator end3_; + typename ParamGenerator::iterator current3_; + const typename ParamGenerator::iterator begin4_; + const typename ParamGenerator::iterator end4_; + typename ParamGenerator::iterator current4_; + const typename ParamGenerator::iterator begin5_; + const typename ParamGenerator::iterator end5_; + typename ParamGenerator::iterator current5_; + const typename ParamGenerator::iterator begin6_; + const typename ParamGenerator::iterator end6_; + typename ParamGenerator::iterator current6_; + const typename ParamGenerator::iterator begin7_; + const typename ParamGenerator::iterator end7_; + typename ParamGenerator::iterator current7_; + const typename ParamGenerator::iterator begin8_; + const typename ParamGenerator::iterator end8_; + typename ParamGenerator::iterator current8_; + const typename ParamGenerator::iterator begin9_; + const typename ParamGenerator::iterator end9_; + typename ParamGenerator::iterator current9_; + const typename ParamGenerator::iterator begin10_; + const typename ParamGenerator::iterator end10_; + typename ParamGenerator::iterator current10_; + ParamType current_value_; + }; // class CartesianProductGenerator10::Iterator + + // No implementation - assignment is unsupported. + void operator=(const CartesianProductGenerator10& other); + + const ParamGenerator g1_; + const ParamGenerator g2_; + const ParamGenerator g3_; + const ParamGenerator g4_; + const ParamGenerator g5_; + const ParamGenerator g6_; + const ParamGenerator g7_; + const ParamGenerator g8_; + const ParamGenerator g9_; + const ParamGenerator g10_; +}; // class CartesianProductGenerator10 + + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Helper classes providing Combine() with polymorphic features. They allow +// casting CartesianProductGeneratorN to ParamGenerator if T is +// convertible to U. +// +template +class CartesianProductHolder2 { + public: +CartesianProductHolder2(const Generator1& g1, const Generator2& g2) + : g1_(g1), g2_(g2) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator2( + static_cast >(g1_), + static_cast >(g2_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder2& other); + + const Generator1 g1_; + const Generator2 g2_; +}; // class CartesianProductHolder2 + +template +class CartesianProductHolder3 { + public: +CartesianProductHolder3(const Generator1& g1, const Generator2& g2, + const Generator3& g3) + : g1_(g1), g2_(g2), g3_(g3) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator3( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder3& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; +}; // class CartesianProductHolder3 + +template +class CartesianProductHolder4 { + public: +CartesianProductHolder4(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator4( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder4& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; +}; // class CartesianProductHolder4 + +template +class CartesianProductHolder5 { + public: +CartesianProductHolder5(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator5( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder5& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; +}; // class CartesianProductHolder5 + +template +class CartesianProductHolder6 { + public: +CartesianProductHolder6(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator6( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder6& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; +}; // class CartesianProductHolder6 + +template +class CartesianProductHolder7 { + public: +CartesianProductHolder7(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator7( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder7& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; +}; // class CartesianProductHolder7 + +template +class CartesianProductHolder8 { + public: +CartesianProductHolder8(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7, const Generator8& g8) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), + g8_(g8) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator8( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_), + static_cast >(g8_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder8& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; + const Generator8 g8_; +}; // class CartesianProductHolder8 + +template +class CartesianProductHolder9 { + public: +CartesianProductHolder9(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7, const Generator8& g8, + const Generator9& g9) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator9( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_), + static_cast >(g8_), + static_cast >(g9_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder9& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; + const Generator8 g8_; + const Generator9 g9_; +}; // class CartesianProductHolder9 + +template +class CartesianProductHolder10 { + public: +CartesianProductHolder10(const Generator1& g1, const Generator2& g2, + const Generator3& g3, const Generator4& g4, const Generator5& g5, + const Generator6& g6, const Generator7& g7, const Generator8& g8, + const Generator9& g9, const Generator10& g10) + : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), + g9_(g9), g10_(g10) {} + template + operator ParamGenerator< ::std::tr1::tuple >() const { + return ParamGenerator< ::std::tr1::tuple >( + new CartesianProductGenerator10( + static_cast >(g1_), + static_cast >(g2_), + static_cast >(g3_), + static_cast >(g4_), + static_cast >(g5_), + static_cast >(g6_), + static_cast >(g7_), + static_cast >(g8_), + static_cast >(g9_), + static_cast >(g10_))); + } + + private: + // No implementation - assignment is unsupported. + void operator=(const CartesianProductHolder10& other); + + const Generator1 g1_; + const Generator2 g2_; + const Generator3 g3_; + const Generator4 g4_; + const Generator5 g5_; + const Generator6 g6_; + const Generator7 g7_; + const Generator8 g8_; + const Generator9 g9_; + const Generator10 g10_; +}; // class CartesianProductHolder10 + +# endif // GTEST_HAS_COMBINE + +} // namespace internal +} // namespace testing + +#endif // GTEST_HAS_PARAM_TEST + +#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ + +#if GTEST_HAS_PARAM_TEST + +namespace testing { + +// Functions producing parameter generators. +// +// Google Test uses these generators to produce parameters for value- +// parameterized tests. When a parameterized test case is instantiated +// with a particular generator, Google Test creates and runs tests +// for each element in the sequence produced by the generator. +// +// In the following sample, tests from test case FooTest are instantiated +// each three times with parameter values 3, 5, and 8: +// +// class FooTest : public TestWithParam { ... }; +// +// TEST_P(FooTest, TestThis) { +// } +// TEST_P(FooTest, TestThat) { +// } +// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8)); +// + +// Range() returns generators providing sequences of values in a range. +// +// Synopsis: +// Range(start, end) +// - returns a generator producing a sequence of values {start, start+1, +// start+2, ..., }. +// Range(start, end, step) +// - returns a generator producing a sequence of values {start, start+step, +// start+step+step, ..., }. +// Notes: +// * The generated sequences never include end. For example, Range(1, 5) +// returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2) +// returns a generator producing {1, 3, 5, 7}. +// * start and end must have the same type. That type may be any integral or +// floating-point type or a user defined type satisfying these conditions: +// * It must be assignable (have operator=() defined). +// * It must have operator+() (operator+(int-compatible type) for +// two-operand version). +// * It must have operator<() defined. +// Elements in the resulting sequences will also have that type. +// * Condition start < end must be satisfied in order for resulting sequences +// to contain any elements. +// +template +internal::ParamGenerator Range(T start, T end, IncrementT step) { + return internal::ParamGenerator( + new internal::RangeGenerator(start, end, step)); +} + +template +internal::ParamGenerator Range(T start, T end) { + return Range(start, end, 1); +} + +// ValuesIn() function allows generation of tests with parameters coming from +// a container. +// +// Synopsis: +// ValuesIn(const T (&array)[N]) +// - returns a generator producing sequences with elements from +// a C-style array. +// ValuesIn(const Container& container) +// - returns a generator producing sequences with elements from +// an STL-style container. +// ValuesIn(Iterator begin, Iterator end) +// - returns a generator producing sequences with elements from +// a range [begin, end) defined by a pair of STL-style iterators. These +// iterators can also be plain C pointers. +// +// Please note that ValuesIn copies the values from the containers +// passed in and keeps them to generate tests in RUN_ALL_TESTS(). +// +// Examples: +// +// This instantiates tests from test case StringTest +// each with C-string values of "foo", "bar", and "baz": +// +// const char* strings[] = {"foo", "bar", "baz"}; +// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings)); +// +// This instantiates tests from test case StlStringTest +// each with STL strings with values "a" and "b": +// +// ::std::vector< ::std::string> GetParameterStrings() { +// ::std::vector< ::std::string> v; +// v.push_back("a"); +// v.push_back("b"); +// return v; +// } +// +// INSTANTIATE_TEST_CASE_P(CharSequence, +// StlStringTest, +// ValuesIn(GetParameterStrings())); +// +// +// This will also instantiate tests from CharTest +// each with parameter values 'a' and 'b': +// +// ::std::list GetParameterChars() { +// ::std::list list; +// list.push_back('a'); +// list.push_back('b'); +// return list; +// } +// ::std::list l = GetParameterChars(); +// INSTANTIATE_TEST_CASE_P(CharSequence2, +// CharTest, +// ValuesIn(l.begin(), l.end())); +// +template +internal::ParamGenerator< + typename ::testing::internal::IteratorTraits::value_type> +ValuesIn(ForwardIterator begin, ForwardIterator end) { + typedef typename ::testing::internal::IteratorTraits + ::value_type ParamType; + return internal::ParamGenerator( + new internal::ValuesInIteratorRangeGenerator(begin, end)); +} + +template +internal::ParamGenerator ValuesIn(const T (&array)[N]) { + return ValuesIn(array, array + N); +} + +template +internal::ParamGenerator ValuesIn( + const Container& container) { + return ValuesIn(container.begin(), container.end()); +} + +// Values() allows generating tests from explicitly specified list of +// parameters. +// +// Synopsis: +// Values(T v1, T v2, ..., T vN) +// - returns a generator producing sequences with elements v1, v2, ..., vN. +// +// For example, this instantiates tests from test case BarTest each +// with values "one", "two", and "three": +// +// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three")); +// +// This instantiates tests from test case BazTest each with values 1, 2, 3.5. +// The exact type of values will depend on the type of parameter in BazTest. +// +// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5)); +// +// Currently, Values() supports from 1 to 50 parameters. +// +template +internal::ValueArray1 Values(T1 v1) { + return internal::ValueArray1(v1); +} + +template +internal::ValueArray2 Values(T1 v1, T2 v2) { + return internal::ValueArray2(v1, v2); +} + +template +internal::ValueArray3 Values(T1 v1, T2 v2, T3 v3) { + return internal::ValueArray3(v1, v2, v3); +} + +template +internal::ValueArray4 Values(T1 v1, T2 v2, T3 v3, T4 v4) { + return internal::ValueArray4(v1, v2, v3, v4); +} + +template +internal::ValueArray5 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5) { + return internal::ValueArray5(v1, v2, v3, v4, v5); +} + +template +internal::ValueArray6 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6) { + return internal::ValueArray6(v1, v2, v3, v4, v5, v6); +} + +template +internal::ValueArray7 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6, T7 v7) { + return internal::ValueArray7(v1, v2, v3, v4, v5, + v6, v7); +} + +template +internal::ValueArray8 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8) { + return internal::ValueArray8(v1, v2, v3, v4, + v5, v6, v7, v8); +} + +template +internal::ValueArray9 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9) { + return internal::ValueArray9(v1, v2, v3, + v4, v5, v6, v7, v8, v9); +} + +template +internal::ValueArray10 Values(T1 v1, + T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10) { + return internal::ValueArray10(v1, + v2, v3, v4, v5, v6, v7, v8, v9, v10); +} + +template +internal::ValueArray11 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11) { + return internal::ValueArray11(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11); +} + +template +internal::ValueArray12 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12) { + return internal::ValueArray12(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12); +} + +template +internal::ValueArray13 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13) { + return internal::ValueArray13(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13); +} + +template +internal::ValueArray14 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) { + return internal::ValueArray14(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, + v14); +} + +template +internal::ValueArray15 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) { + return internal::ValueArray15(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, + v13, v14, v15); +} + +template +internal::ValueArray16 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16) { + return internal::ValueArray16(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, + v12, v13, v14, v15, v16); +} + +template +internal::ValueArray17 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17) { + return internal::ValueArray17(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, + v11, v12, v13, v14, v15, v16, v17); +} + +template +internal::ValueArray18 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, + T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18) { + return internal::ValueArray18(v1, v2, v3, v4, v5, v6, v7, v8, v9, + v10, v11, v12, v13, v14, v15, v16, v17, v18); +} + +template +internal::ValueArray19 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, + T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, + T15 v15, T16 v16, T17 v17, T18 v18, T19 v19) { + return internal::ValueArray19(v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19); +} + +template +internal::ValueArray20 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20) { + return internal::ValueArray20(v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20); +} + +template +internal::ValueArray21 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21) { + return internal::ValueArray21(v1, v2, v3, v4, v5, v6, + v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21); +} + +template +internal::ValueArray22 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22) { + return internal::ValueArray22(v1, v2, v3, v4, + v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22); +} + +template +internal::ValueArray23 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23) { + return internal::ValueArray23(v1, v2, v3, + v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23); +} + +template +internal::ValueArray24 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24) { + return internal::ValueArray24(v1, v2, + v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, + v19, v20, v21, v22, v23, v24); +} + +template +internal::ValueArray25 Values(T1 v1, + T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, + T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, + T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25) { + return internal::ValueArray25(v1, + v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, + v18, v19, v20, v21, v22, v23, v24, v25); +} + +template +internal::ValueArray26 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26) { + return internal::ValueArray26(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, + v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26); +} + +template +internal::ValueArray27 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27) { + return internal::ValueArray27(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, + v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27); +} + +template +internal::ValueArray28 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28) { + return internal::ValueArray28(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, + v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, + v28); +} + +template +internal::ValueArray29 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29) { + return internal::ValueArray29(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, + v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, + v27, v28, v29); +} + +template +internal::ValueArray30 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, + T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, + T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) { + return internal::ValueArray30(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, + v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, + v26, v27, v28, v29, v30); +} + +template +internal::ValueArray31 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) { + return internal::ValueArray31(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, + v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, + v25, v26, v27, v28, v29, v30, v31); +} + +template +internal::ValueArray32 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32) { + return internal::ValueArray32(v1, v2, v3, v4, v5, v6, v7, v8, v9, + v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32); +} + +template +internal::ValueArray33 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, + T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33) { + return internal::ValueArray33(v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32, v33); +} + +template +internal::ValueArray34 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, + T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, + T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, + T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, + T31 v31, T32 v32, T33 v33, T34 v34) { + return internal::ValueArray34(v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, + v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34); +} + +template +internal::ValueArray35 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, + T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, + T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35) { + return internal::ValueArray35(v1, v2, v3, v4, v5, v6, + v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, + v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35); +} + +template +internal::ValueArray36 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, + T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, + T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36) { + return internal::ValueArray36(v1, v2, v3, v4, + v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, + v34, v35, v36); +} + +template +internal::ValueArray37 Values(T1 v1, T2 v2, T3 v3, + T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, + T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, + T37 v37) { + return internal::ValueArray37(v1, v2, v3, + v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, + v34, v35, v36, v37); +} + +template +internal::ValueArray38 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, + T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, + T37 v37, T38 v38) { + return internal::ValueArray38(v1, v2, + v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, + v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, + v33, v34, v35, v36, v37, v38); +} + +template +internal::ValueArray39 Values(T1 v1, T2 v2, + T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, + T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, + T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, + T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, + T37 v37, T38 v38, T39 v39) { + return internal::ValueArray39(v1, + v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, + v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, + v32, v33, v34, v35, v36, v37, v38, v39); +} + +template +internal::ValueArray40 Values(T1 v1, + T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, + T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, + T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, + T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, + T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) { + return internal::ValueArray40(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, + v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, + v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40); +} + +template +internal::ValueArray41 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41) { + return internal::ValueArray41(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, + v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, + v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41); +} + +template +internal::ValueArray42 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42) { + return internal::ValueArray42(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, + v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, + v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, + v42); +} + +template +internal::ValueArray43 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43) { + return internal::ValueArray43(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, + v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, + v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, + v41, v42, v43); +} + +template +internal::ValueArray44 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, + T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, + T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, + T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, + T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, + T42 v42, T43 v43, T44 v44) { + return internal::ValueArray44(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, + v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, + v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, + v40, v41, v42, v43, v44); +} + +template +internal::ValueArray45 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, + T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, + T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, + T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, + T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, + T41 v41, T42 v42, T43 v43, T44 v44, T45 v45) { + return internal::ValueArray45(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, + v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, + v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, + v39, v40, v41, v42, v43, v44, v45); +} + +template +internal::ValueArray46 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, + T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) { + return internal::ValueArray46(v1, v2, v3, v4, v5, v6, v7, v8, v9, + v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, + v38, v39, v40, v41, v42, v43, v44, v45, v46); +} + +template +internal::ValueArray47 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, + T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, + T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) { + return internal::ValueArray47(v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, + v38, v39, v40, v41, v42, v43, v44, v45, v46, v47); +} + +template +internal::ValueArray48 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, + T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, + T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, + T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, + T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, + T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, + T48 v48) { + return internal::ValueArray48(v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, + v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, + v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48); +} + +template +internal::ValueArray49 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, + T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, + T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, + T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, + T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, + T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, + T47 v47, T48 v48, T49 v49) { + return internal::ValueArray49(v1, v2, v3, v4, v5, v6, + v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, + v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, + v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49); +} + +template +internal::ValueArray50 Values(T1 v1, T2 v2, T3 v3, T4 v4, + T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, + T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, + T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, + T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, + T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, + T46 v46, T47 v47, T48 v48, T49 v49, T50 v50) { + return internal::ValueArray50(v1, v2, v3, v4, + v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, + v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, + v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, + v48, v49, v50); +} + +// Bool() allows generating tests with parameters in a set of (false, true). +// +// Synopsis: +// Bool() +// - returns a generator producing sequences with elements {false, true}. +// +// It is useful when testing code that depends on Boolean flags. Combinations +// of multiple flags can be tested when several Bool()'s are combined using +// Combine() function. +// +// In the following example all tests in the test case FlagDependentTest +// will be instantiated twice with parameters false and true. +// +// class FlagDependentTest : public testing::TestWithParam { +// virtual void SetUp() { +// external_flag = GetParam(); +// } +// } +// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool()); +// +inline internal::ParamGenerator Bool() { + return Values(false, true); +} + +# if GTEST_HAS_COMBINE +// Combine() allows the user to combine two or more sequences to produce +// values of a Cartesian product of those sequences' elements. +// +// Synopsis: +// Combine(gen1, gen2, ..., genN) +// - returns a generator producing sequences with elements coming from +// the Cartesian product of elements from the sequences generated by +// gen1, gen2, ..., genN. The sequence elements will have a type of +// tuple where T1, T2, ..., TN are the types +// of elements from sequences produces by gen1, gen2, ..., genN. +// +// Combine can have up to 10 arguments. This number is currently limited +// by the maximum number of elements in the tuple implementation used by Google +// Test. +// +// Example: +// +// This will instantiate tests in test case AnimalTest each one with +// the parameter values tuple("cat", BLACK), tuple("cat", WHITE), +// tuple("dog", BLACK), and tuple("dog", WHITE): +// +// enum Color { BLACK, GRAY, WHITE }; +// class AnimalTest +// : public testing::TestWithParam > {...}; +// +// TEST_P(AnimalTest, AnimalLooksNice) {...} +// +// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest, +// Combine(Values("cat", "dog"), +// Values(BLACK, WHITE))); +// +// This will instantiate tests in FlagDependentTest with all variations of two +// Boolean flags: +// +// class FlagDependentTest +// : public testing::TestWithParam > { +// virtual void SetUp() { +// // Assigns external_flag_1 and external_flag_2 values from the tuple. +// tie(external_flag_1, external_flag_2) = GetParam(); +// } +// }; +// +// TEST_P(FlagDependentTest, TestFeature1) { +// // Test your code using external_flag_1 and external_flag_2 here. +// } +// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest, +// Combine(Bool(), Bool())); +// +template +internal::CartesianProductHolder2 Combine( + const Generator1& g1, const Generator2& g2) { + return internal::CartesianProductHolder2( + g1, g2); +} + +template +internal::CartesianProductHolder3 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3) { + return internal::CartesianProductHolder3( + g1, g2, g3); +} + +template +internal::CartesianProductHolder4 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4) { + return internal::CartesianProductHolder4( + g1, g2, g3, g4); +} + +template +internal::CartesianProductHolder5 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5) { + return internal::CartesianProductHolder5( + g1, g2, g3, g4, g5); +} + +template +internal::CartesianProductHolder6 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6) { + return internal::CartesianProductHolder6( + g1, g2, g3, g4, g5, g6); +} + +template +internal::CartesianProductHolder7 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7) { + return internal::CartesianProductHolder7( + g1, g2, g3, g4, g5, g6, g7); +} + +template +internal::CartesianProductHolder8 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7, const Generator8& g8) { + return internal::CartesianProductHolder8( + g1, g2, g3, g4, g5, g6, g7, g8); +} + +template +internal::CartesianProductHolder9 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7, const Generator8& g8, const Generator9& g9) { + return internal::CartesianProductHolder9( + g1, g2, g3, g4, g5, g6, g7, g8, g9); +} + +template +internal::CartesianProductHolder10 Combine( + const Generator1& g1, const Generator2& g2, const Generator3& g3, + const Generator4& g4, const Generator5& g5, const Generator6& g6, + const Generator7& g7, const Generator8& g8, const Generator9& g9, + const Generator10& g10) { + return internal::CartesianProductHolder10( + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10); +} +# endif // GTEST_HAS_COMBINE + + + +# define TEST_P(test_case_name, test_name) \ + class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ + : public test_case_name { \ + public: \ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \ + virtual void TestBody(); \ + private: \ + static int AddToRegistry() { \ + ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ + GetTestCasePatternHolder(\ + #test_case_name, __FILE__, __LINE__)->AddTestPattern(\ + #test_case_name, \ + #test_name, \ + new ::testing::internal::TestMetaFactory< \ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \ + return 0; \ + } \ + static int gtest_registering_dummy_; \ + GTEST_DISALLOW_COPY_AND_ASSIGN_(\ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \ + }; \ + int GTEST_TEST_CLASS_NAME_(test_case_name, \ + test_name)::gtest_registering_dummy_ = \ + GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \ + void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() + +# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \ + ::testing::internal::ParamGenerator \ + gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \ + int gtest_##prefix##test_case_name##_dummy_ = \ + ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ + GetTestCasePatternHolder(\ + #test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\ + #prefix, \ + >est_##prefix##test_case_name##_EvalGenerator_, \ + __FILE__, __LINE__) + +} // namespace testing + +#endif // GTEST_HAS_PARAM_TEST + +#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ +// Copyright 2006, 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) +// +// Google C++ Testing Framework definitions useful in production code. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_ + +// When you need to test the private or protected members of a class, +// use the FRIEND_TEST macro to declare your tests as friends of the +// class. For example: +// +// class MyClass { +// private: +// void MyMethod(); +// FRIEND_TEST(MyClassTest, MyMethod); +// }; +// +// class MyClassTest : public testing::Test { +// // ... +// }; +// +// TEST_F(MyClassTest, MyMethod) { +// // Can call MyClass::MyMethod() here. +// } + +#define FRIEND_TEST(test_case_name, test_name)\ +friend class test_case_name##_##test_name##_Test + +#endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_ +// Copyright 2008, 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: mheule@google.com (Markus Heule) +// + +#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ +#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ + +#include +#include + +namespace testing { + +// A copyable object representing the result of a test part (i.e. an +// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()). +// +// Don't inherit from TestPartResult as its destructor is not virtual. +class GTEST_API_ TestPartResult { + public: + // The possible outcomes of a test part (i.e. an assertion or an + // explicit SUCCEED(), FAIL(), or ADD_FAILURE()). + enum Type { + kSuccess, // Succeeded. + kNonFatalFailure, // Failed but the test can continue. + kFatalFailure // Failed and the test should be terminated. + }; + + // C'tor. TestPartResult does NOT have a default constructor. + // Always use this constructor (with parameters) to create a + // TestPartResult object. + TestPartResult(Type a_type, + const char* a_file_name, + int a_line_number, + const char* a_message) + : type_(a_type), + file_name_(a_file_name == NULL ? "" : a_file_name), + line_number_(a_line_number), + summary_(ExtractSummary(a_message)), + message_(a_message) { + } + + // Gets the outcome of the test part. + Type type() const { return type_; } + + // Gets the name of the source file where the test part took place, or + // NULL if it's unknown. + const char* file_name() const { + return file_name_.empty() ? NULL : file_name_.c_str(); + } + + // Gets the line in the source file where the test part took place, + // or -1 if it's unknown. + int line_number() const { return line_number_; } + + // Gets the summary of the failure message. + const char* summary() const { return summary_.c_str(); } + + // Gets the message associated with the test part. + const char* message() const { return message_.c_str(); } + + // Returns true iff the test part passed. + bool passed() const { return type_ == kSuccess; } + + // Returns true iff the test part failed. + bool failed() const { return type_ != kSuccess; } + + // Returns true iff the test part non-fatally failed. + bool nonfatally_failed() const { return type_ == kNonFatalFailure; } + + // Returns true iff the test part fatally failed. + bool fatally_failed() const { return type_ == kFatalFailure; } + + private: + Type type_; + + // Gets the summary of the failure message by omitting the stack + // trace in it. + static std::string ExtractSummary(const char* message); + + // The name of the source file where the test part took place, or + // "" if the source file is unknown. + std::string file_name_; + // The line in the source file where the test part took place, or -1 + // if the line number is unknown. + int line_number_; + std::string summary_; // The test failure summary. + std::string message_; // The test failure message. +}; + +// Prints a TestPartResult object. +std::ostream& operator<<(std::ostream& os, const TestPartResult& result); + +// An array of TestPartResult objects. +// +// Don't inherit from TestPartResultArray as its destructor is not +// virtual. +class GTEST_API_ TestPartResultArray { + public: + TestPartResultArray() {} + + // Appends the given TestPartResult to the array. + void Append(const TestPartResult& result); + + // Returns the TestPartResult at the given index (0-based). + const TestPartResult& GetTestPartResult(int index) const; + + // Returns the number of TestPartResult objects in the array. + int size() const; + + private: + std::vector array_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray); +}; + +// This interface knows how to report a test part result. +class TestPartResultReporterInterface { + public: + virtual ~TestPartResultReporterInterface() {} + + virtual void ReportTestPartResult(const TestPartResult& result) = 0; +}; + +namespace internal { + +// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a +// statement generates new fatal failures. To do so it registers itself as the +// current test part result reporter. Besides checking if fatal failures were +// reported, it only delegates the reporting to the former result reporter. +// The original result reporter is restored in the destructor. +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +class GTEST_API_ HasNewFatalFailureHelper + : public TestPartResultReporterInterface { + public: + HasNewFatalFailureHelper(); + virtual ~HasNewFatalFailureHelper(); + virtual void ReportTestPartResult(const TestPartResult& result); + bool has_new_fatal_failure() const { return has_new_fatal_failure_; } + private: + bool has_new_fatal_failure_; + TestPartResultReporterInterface* original_reporter_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper); +}; + +} // namespace internal + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ +// Copyright 2008 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) + +#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ +#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ + +// This header implements typed tests and type-parameterized tests. + +// Typed (aka type-driven) tests repeat the same test for types in a +// list. You must know which types you want to test with when writing +// typed tests. Here's how you do it: + +#if 0 + +// First, define a fixture class template. It should be parameterized +// by a type. Remember to derive it from testing::Test. +template +class FooTest : public testing::Test { + public: + ... + typedef std::list List; + static T shared_; + T value_; +}; + +// Next, associate a list of types with the test case, which will be +// repeated for each type in the list. The typedef is necessary for +// the macro to parse correctly. +typedef testing::Types MyTypes; +TYPED_TEST_CASE(FooTest, MyTypes); + +// If the type list contains only one type, you can write that type +// directly without Types<...>: +// TYPED_TEST_CASE(FooTest, int); + +// Then, use TYPED_TEST() instead of TEST_F() to define as many typed +// tests for this test case as you want. +TYPED_TEST(FooTest, DoesBlah) { + // Inside a test, refer to TypeParam to get the type parameter. + // Since we are inside a derived class template, C++ requires use to + // visit the members of FooTest via 'this'. + TypeParam n = this->value_; + + // To visit static members of the fixture, add the TestFixture:: + // prefix. + n += TestFixture::shared_; + + // To refer to typedefs in the fixture, add the "typename + // TestFixture::" prefix. + typename TestFixture::List values; + values.push_back(n); + ... +} + +TYPED_TEST(FooTest, HasPropertyA) { ... } + +#endif // 0 + +// Type-parameterized tests are abstract test patterns parameterized +// by a type. Compared with typed tests, type-parameterized tests +// allow you to define the test pattern without knowing what the type +// parameters are. The defined pattern can be instantiated with +// different types any number of times, in any number of translation +// units. +// +// If you are designing an interface or concept, you can define a +// suite of type-parameterized tests to verify properties that any +// valid implementation of the interface/concept should have. Then, +// each implementation can easily instantiate the test suite to verify +// that it conforms to the requirements, without having to write +// similar tests repeatedly. Here's an example: + +#if 0 + +// First, define a fixture class template. It should be parameterized +// by a type. Remember to derive it from testing::Test. +template +class FooTest : public testing::Test { + ... +}; + +// Next, declare that you will define a type-parameterized test case +// (the _P suffix is for "parameterized" or "pattern", whichever you +// prefer): +TYPED_TEST_CASE_P(FooTest); + +// Then, use TYPED_TEST_P() to define as many type-parameterized tests +// for this type-parameterized test case as you want. +TYPED_TEST_P(FooTest, DoesBlah) { + // Inside a test, refer to TypeParam to get the type parameter. + TypeParam n = 0; + ... +} + +TYPED_TEST_P(FooTest, HasPropertyA) { ... } + +// Now the tricky part: you need to register all test patterns before +// you can instantiate them. The first argument of the macro is the +// test case name; the rest are the names of the tests in this test +// case. +REGISTER_TYPED_TEST_CASE_P(FooTest, + DoesBlah, HasPropertyA); + +// Finally, you are free to instantiate the pattern with the types you +// want. If you put the above code in a header file, you can #include +// it in multiple C++ source files and instantiate it multiple times. +// +// To distinguish different instances of the pattern, the first +// argument to the INSTANTIATE_* macro is a prefix that will be added +// to the actual test case name. Remember to pick unique prefixes for +// different instances. +typedef testing::Types MyTypes; +INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes); + +// If the type list contains only one type, you can write that type +// directly without Types<...>: +// INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int); + +#endif // 0 + + +// Implements typed tests. + +#if GTEST_HAS_TYPED_TEST + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Expands to the name of the typedef for the type parameters of the +// given test case. +# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_ + +// The 'Types' template argument below must have spaces around it +// since some compilers may choke on '>>' when passing a template +// instance (e.g. Types) +# define TYPED_TEST_CASE(CaseName, Types) \ + typedef ::testing::internal::TypeList< Types >::type \ + GTEST_TYPE_PARAMS_(CaseName) + +# define TYPED_TEST(CaseName, TestName) \ + template \ + class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \ + : public CaseName { \ + private: \ + typedef CaseName TestFixture; \ + typedef gtest_TypeParam_ TypeParam; \ + virtual void TestBody(); \ + }; \ + bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \ + ::testing::internal::TypeParameterizedTest< \ + CaseName, \ + ::testing::internal::TemplateSel< \ + GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \ + GTEST_TYPE_PARAMS_(CaseName)>::Register(\ + "", #CaseName, #TestName, 0); \ + template \ + void GTEST_TEST_CLASS_NAME_(CaseName, TestName)::TestBody() + +#endif // GTEST_HAS_TYPED_TEST + +// Implements type-parameterized tests. + +#if GTEST_HAS_TYPED_TEST_P + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Expands to the namespace name that the type-parameterized tests for +// the given type-parameterized test case are defined in. The exact +// name of the namespace is subject to change without notice. +# define GTEST_CASE_NAMESPACE_(TestCaseName) \ + gtest_case_##TestCaseName##_ + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Expands to the name of the variable used to remember the names of +// the defined tests in the given test case. +# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \ + gtest_typed_test_case_p_state_##TestCaseName##_ + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY. +// +// Expands to the name of the variable used to remember the names of +// the registered tests in the given test case. +# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \ + gtest_registered_test_names_##TestCaseName##_ + +// The variables defined in the type-parameterized test macros are +// static as typically these macros are used in a .h file that can be +// #included in multiple translation units linked together. +# define TYPED_TEST_CASE_P(CaseName) \ + static ::testing::internal::TypedTestCasePState \ + GTEST_TYPED_TEST_CASE_P_STATE_(CaseName) + +# define TYPED_TEST_P(CaseName, TestName) \ + namespace GTEST_CASE_NAMESPACE_(CaseName) { \ + template \ + class TestName : public CaseName { \ + private: \ + typedef CaseName TestFixture; \ + typedef gtest_TypeParam_ TypeParam; \ + virtual void TestBody(); \ + }; \ + static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \ + GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\ + __FILE__, __LINE__, #CaseName, #TestName); \ + } \ + template \ + void GTEST_CASE_NAMESPACE_(CaseName)::TestName::TestBody() + +# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \ + namespace GTEST_CASE_NAMESPACE_(CaseName) { \ + typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \ + } \ + static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \ + GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\ + __FILE__, __LINE__, #__VA_ARGS__) + +// The 'Types' template argument below must have spaces around it +// since some compilers may choke on '>>' when passing a template +// instance (e.g. Types) +# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \ + bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \ + ::testing::internal::TypeParameterizedTestCase::type>::Register(\ + #Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName)) + +#endif // GTEST_HAS_TYPED_TEST_P + +#endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ + +// Depending on the platform, different string classes are available. +// On Linux, in addition to ::std::string, Google also makes use of +// class ::string, which has the same interface as ::std::string, but +// has a different implementation. +// +// The user can define GTEST_HAS_GLOBAL_STRING to 1 to indicate that +// ::string is available AND is a distinct type to ::std::string, or +// define it to 0 to indicate otherwise. +// +// If the user's ::std::string and ::string are the same class due to +// aliasing, he should define GTEST_HAS_GLOBAL_STRING to 0. +// +// If the user doesn't define GTEST_HAS_GLOBAL_STRING, it is defined +// heuristically. + +namespace testing { + +// Declares the flags. + +// This flag temporary enables the disabled tests. +GTEST_DECLARE_bool_(also_run_disabled_tests); + +// This flag brings the debugger on an assertion failure. +GTEST_DECLARE_bool_(break_on_failure); + +// This flag controls whether Google Test catches all test-thrown exceptions +// and logs them as failures. +GTEST_DECLARE_bool_(catch_exceptions); + +// This flag enables using colors in terminal output. Available values are +// "yes" to enable colors, "no" (disable colors), or "auto" (the default) +// to let Google Test decide. +GTEST_DECLARE_string_(color); + +// This flag sets up the filter to select by name using a glob pattern +// the tests to run. If the filter is not given all tests are executed. +GTEST_DECLARE_string_(filter); + +// This flag causes the Google Test to list tests. None of the tests listed +// are actually run if the flag is provided. +GTEST_DECLARE_bool_(list_tests); + +// This flag controls whether Google Test emits a detailed XML report to a file +// in addition to its normal textual output. +GTEST_DECLARE_string_(output); + +// This flags control whether Google Test prints the elapsed time for each +// test. +GTEST_DECLARE_bool_(print_time); + +// This flag specifies the random number seed. +GTEST_DECLARE_int32_(random_seed); + +// This flag sets how many times the tests are repeated. The default value +// is 1. If the value is -1 the tests are repeating forever. +GTEST_DECLARE_int32_(repeat); + +// This flag controls whether Google Test includes Google Test internal +// stack frames in failure stack traces. +GTEST_DECLARE_bool_(show_internal_stack_frames); + +// When this flag is specified, tests' order is randomized on every iteration. +GTEST_DECLARE_bool_(shuffle); + +// This flag specifies the maximum number of stack frames to be +// printed in a failure message. +GTEST_DECLARE_int32_(stack_trace_depth); + +// When this flag is specified, a failed assertion will throw an +// exception if exceptions are enabled, or exit the program with a +// non-zero code otherwise. +GTEST_DECLARE_bool_(throw_on_failure); + +// When this flag is set with a "host:port" string, on supported +// platforms test results are streamed to the specified port on +// the specified host machine. +GTEST_DECLARE_string_(stream_result_to); + +// The upper limit for valid stack trace depths. +const int kMaxStackTraceDepth = 100; + +namespace internal { + +class AssertHelper; +class DefaultGlobalTestPartResultReporter; +class ExecDeathTest; +class NoExecDeathTest; +class FinalSuccessChecker; +class GTestFlagSaver; +class StreamingListenerTest; +class TestResultAccessor; +class TestEventListenersAccessor; +class TestEventRepeater; +class UnitTestRecordPropertyTestHelper; +class WindowsDeathTest; +class UnitTestImpl* GetUnitTestImpl(); +void ReportFailureInUnknownLocation(TestPartResult::Type result_type, + const std::string& message); + +} // namespace internal + +// The friend relationship of some of these classes is cyclic. +// If we don't forward declare them the compiler might confuse the classes +// in friendship clauses with same named classes on the scope. +class Test; +class TestCase; +class TestInfo; +class UnitTest; + +// A class for indicating whether an assertion was successful. When +// the assertion wasn't successful, the AssertionResult object +// remembers a non-empty message that describes how it failed. +// +// To create an instance of this class, use one of the factory functions +// (AssertionSuccess() and AssertionFailure()). +// +// This class is useful for two purposes: +// 1. Defining predicate functions to be used with Boolean test assertions +// EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts +// 2. Defining predicate-format functions to be +// used with predicate assertions (ASSERT_PRED_FORMAT*, etc). +// +// For example, if you define IsEven predicate: +// +// testing::AssertionResult IsEven(int n) { +// if ((n % 2) == 0) +// return testing::AssertionSuccess(); +// else +// return testing::AssertionFailure() << n << " is odd"; +// } +// +// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5))) +// will print the message +// +// Value of: IsEven(Fib(5)) +// Actual: false (5 is odd) +// Expected: true +// +// instead of a more opaque +// +// Value of: IsEven(Fib(5)) +// Actual: false +// Expected: true +// +// in case IsEven is a simple Boolean predicate. +// +// If you expect your predicate to be reused and want to support informative +// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up +// about half as often as positive ones in our tests), supply messages for +// both success and failure cases: +// +// testing::AssertionResult IsEven(int n) { +// if ((n % 2) == 0) +// return testing::AssertionSuccess() << n << " is even"; +// else +// return testing::AssertionFailure() << n << " is odd"; +// } +// +// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print +// +// Value of: IsEven(Fib(6)) +// Actual: true (8 is even) +// Expected: false +// +// NB: Predicates that support negative Boolean assertions have reduced +// performance in positive ones so be careful not to use them in tests +// that have lots (tens of thousands) of positive Boolean assertions. +// +// To use this class with EXPECT_PRED_FORMAT assertions such as: +// +// // Verifies that Foo() returns an even number. +// EXPECT_PRED_FORMAT1(IsEven, Foo()); +// +// you need to define: +// +// testing::AssertionResult IsEven(const char* expr, int n) { +// if ((n % 2) == 0) +// return testing::AssertionSuccess(); +// else +// return testing::AssertionFailure() +// << "Expected: " << expr << " is even\n Actual: it's " << n; +// } +// +// If Foo() returns 5, you will see the following message: +// +// Expected: Foo() is even +// Actual: it's 5 +// +class GTEST_API_ AssertionResult { + public: + // Copy constructor. + // Used in EXPECT_TRUE/FALSE(assertion_result). + AssertionResult(const AssertionResult& other); + // Used in the EXPECT_TRUE/FALSE(bool_expression). + explicit AssertionResult(bool success) : success_(success) {} + + // Returns true iff the assertion succeeded. + operator bool() const { return success_; } // NOLINT + + // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. + AssertionResult operator!() const; + + // Returns the text streamed into this AssertionResult. Test assertions + // use it when they fail (i.e., the predicate's outcome doesn't match the + // assertion's expectation). When nothing has been streamed into the + // object, returns an empty string. + const char* message() const { + return message_.get() != NULL ? message_->c_str() : ""; + } + // TODO(vladl@google.com): Remove this after making sure no clients use it. + // Deprecated; please use message() instead. + const char* failure_message() const { return message(); } + + // Streams a custom failure message into this object. + template AssertionResult& operator<<(const T& value) { + AppendMessage(Message() << value); + return *this; + } + + // Allows streaming basic output manipulators such as endl or flush into + // this object. + AssertionResult& operator<<( + ::std::ostream& (*basic_manipulator)(::std::ostream& stream)) { + AppendMessage(Message() << basic_manipulator); + return *this; + } + + private: + // Appends the contents of message to message_. + void AppendMessage(const Message& a_message) { + if (message_.get() == NULL) + message_.reset(new ::std::string); + message_->append(a_message.GetString().c_str()); + } + + // Stores result of the assertion predicate. + bool success_; + // Stores the message describing the condition in case the expectation + // construct is not satisfied with the predicate's outcome. + // Referenced via a pointer to avoid taking too much stack frame space + // with test assertions. + internal::scoped_ptr< ::std::string> message_; + + GTEST_DISALLOW_ASSIGN_(AssertionResult); +}; + +// Makes a successful assertion result. +GTEST_API_ AssertionResult AssertionSuccess(); + +// Makes a failed assertion result. +GTEST_API_ AssertionResult AssertionFailure(); + +// Makes a failed assertion result with the given failure message. +// Deprecated; use AssertionFailure() << msg. +GTEST_API_ AssertionResult AssertionFailure(const Message& msg); + +// The abstract class that all tests inherit from. +// +// In Google Test, a unit test program contains one or many TestCases, and +// each TestCase contains one or many Tests. +// +// When you define a test using the TEST macro, you don't need to +// explicitly derive from Test - the TEST macro automatically does +// this for you. +// +// The only time you derive from Test is when defining a test fixture +// to be used a TEST_F. For example: +// +// class FooTest : public testing::Test { +// protected: +// virtual void SetUp() { ... } +// virtual void TearDown() { ... } +// ... +// }; +// +// TEST_F(FooTest, Bar) { ... } +// TEST_F(FooTest, Baz) { ... } +// +// Test is not copyable. +class GTEST_API_ Test { + public: + friend class TestInfo; + + // Defines types for pointers to functions that set up and tear down + // a test case. + typedef internal::SetUpTestCaseFunc SetUpTestCaseFunc; + typedef internal::TearDownTestCaseFunc TearDownTestCaseFunc; + + // The d'tor is virtual as we intend to inherit from Test. + virtual ~Test(); + + // Sets up the stuff shared by all tests in this test case. + // + // Google Test will call Foo::SetUpTestCase() before running the first + // test in test case Foo. Hence a sub-class can define its own + // SetUpTestCase() method to shadow the one defined in the super + // class. + static void SetUpTestCase() {} + + // Tears down the stuff shared by all tests in this test case. + // + // Google Test will call Foo::TearDownTestCase() after running the last + // test in test case Foo. Hence a sub-class can define its own + // TearDownTestCase() method to shadow the one defined in the super + // class. + static void TearDownTestCase() {} + + // Returns true iff the current test has a fatal failure. + static bool HasFatalFailure(); + + // Returns true iff the current test has a non-fatal failure. + static bool HasNonfatalFailure(); + + // Returns true iff the current test has a (either fatal or + // non-fatal) failure. + static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); } + + // Logs a property for the current test, test case, or for the entire + // invocation of the test program when used outside of the context of a + // test case. Only the last value for a given key is remembered. These + // are public static so they can be called from utility functions that are + // not members of the test fixture. Calls to RecordProperty made during + // lifespan of the test (from the moment its constructor starts to the + // moment its destructor finishes) will be output in XML as attributes of + // the element. Properties recorded from fixture's + // SetUpTestCase or TearDownTestCase are logged as attributes of the + // corresponding element. Calls to RecordProperty made in the + // global context (before or after invocation of RUN_ALL_TESTS and from + // SetUp/TearDown method of Environment objects registered with Google + // Test) will be output as attributes of the element. + static void RecordProperty(const std::string& key, const std::string& value); + static void RecordProperty(const std::string& key, int value); + + protected: + // Creates a Test object. + Test(); + + // Sets up the test fixture. + virtual void SetUp(); + + // Tears down the test fixture. + virtual void TearDown(); + + private: + // Returns true iff the current test has the same fixture class as + // the first test in the current test case. + static bool HasSameFixtureClass(); + + // Runs the test after the test fixture has been set up. + // + // A sub-class must implement this to define the test logic. + // + // DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM. + // Instead, use the TEST or TEST_F macro. + virtual void TestBody() = 0; + + // Sets up, executes, and tears down the test. + void Run(); + + // Deletes self. We deliberately pick an unusual name for this + // internal method to avoid clashing with names used in user TESTs. + void DeleteSelf_() { delete this; } + + // Uses a GTestFlagSaver to save and restore all Google Test flags. + const internal::GTestFlagSaver* const gtest_flag_saver_; + + // Often a user mis-spells SetUp() as Setup() and spends a long time + // wondering why it is never called by Google Test. The declaration of + // the following method is solely for catching such an error at + // compile time: + // + // - The return type is deliberately chosen to be not void, so it + // will be a conflict if a user declares void Setup() in his test + // fixture. + // + // - This method is private, so it will be another compiler error + // if a user calls it from his test fixture. + // + // DO NOT OVERRIDE THIS FUNCTION. + // + // If you see an error about overriding the following function or + // about it being private, you have mis-spelled SetUp() as Setup(). + struct Setup_should_be_spelled_SetUp {}; + virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; } + + // We disallow copying Tests. + GTEST_DISALLOW_COPY_AND_ASSIGN_(Test); +}; + +typedef internal::TimeInMillis TimeInMillis; + +// A copyable object representing a user specified test property which can be +// output as a key/value string pair. +// +// Don't inherit from TestProperty as its destructor is not virtual. +class TestProperty { + public: + // C'tor. TestProperty does NOT have a default constructor. + // Always use this constructor (with parameters) to create a + // TestProperty object. + TestProperty(const std::string& a_key, const std::string& a_value) : + key_(a_key), value_(a_value) { + } + + // Gets the user supplied key. + const char* key() const { + return key_.c_str(); + } + + // Gets the user supplied value. + const char* value() const { + return value_.c_str(); + } + + // Sets a new value, overriding the one supplied in the constructor. + void SetValue(const std::string& new_value) { + value_ = new_value; + } + + private: + // The key supplied by the user. + std::string key_; + // The value supplied by the user. + std::string value_; +}; + +// The result of a single Test. This includes a list of +// TestPartResults, a list of TestProperties, a count of how many +// death tests there are in the Test, and how much time it took to run +// the Test. +// +// TestResult is not copyable. +class GTEST_API_ TestResult { + public: + // Creates an empty TestResult. + TestResult(); + + // D'tor. Do not inherit from TestResult. + ~TestResult(); + + // Gets the number of all test parts. This is the sum of the number + // of successful test parts and the number of failed test parts. + int total_part_count() const; + + // Returns the number of the test properties. + int test_property_count() const; + + // Returns true iff the test passed (i.e. no test part failed). + bool Passed() const { return !Failed(); } + + // Returns true iff the test failed. + bool Failed() const; + + // Returns true iff the test fatally failed. + bool HasFatalFailure() const; + + // Returns true iff the test has a non-fatal failure. + bool HasNonfatalFailure() const; + + // Returns the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns the i-th test part result among all the results. i can range + // from 0 to test_property_count() - 1. If i is not in that range, aborts + // the program. + const TestPartResult& GetTestPartResult(int i) const; + + // Returns the i-th test property. i can range from 0 to + // test_property_count() - 1. If i is not in that range, aborts the + // program. + const TestProperty& GetTestProperty(int i) const; + + private: + friend class TestInfo; + friend class TestCase; + friend class UnitTest; + friend class internal::DefaultGlobalTestPartResultReporter; + friend class internal::ExecDeathTest; + friend class internal::TestResultAccessor; + friend class internal::UnitTestImpl; + friend class internal::WindowsDeathTest; + + // Gets the vector of TestPartResults. + const std::vector& test_part_results() const { + return test_part_results_; + } + + // Gets the vector of TestProperties. + const std::vector& test_properties() const { + return test_properties_; + } + + // Sets the elapsed time. + void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; } + + // Adds a test property to the list. The property is validated and may add + // a non-fatal failure if invalid (e.g., if it conflicts with reserved + // key names). If a property is already recorded for the same key, the + // value will be updated, rather than storing multiple values for the same + // key. xml_element specifies the element for which the property is being + // recorded and is used for validation. + void RecordProperty(const std::string& xml_element, + const TestProperty& test_property); + + // Adds a failure if the key is a reserved attribute of Google Test + // testcase tags. Returns true if the property is valid. + // TODO(russr): Validate attribute names are legal and human readable. + static bool ValidateTestProperty(const std::string& xml_element, + const TestProperty& test_property); + + // Adds a test part result to the list. + void AddTestPartResult(const TestPartResult& test_part_result); + + // Returns the death test count. + int death_test_count() const { return death_test_count_; } + + // Increments the death test count, returning the new count. + int increment_death_test_count() { return ++death_test_count_; } + + // Clears the test part results. + void ClearTestPartResults(); + + // Clears the object. + void Clear(); + + // Protects mutable state of the property vector and of owned + // properties, whose values may be updated. + internal::Mutex test_properites_mutex_; + + // The vector of TestPartResults + std::vector test_part_results_; + // The vector of TestProperties + std::vector test_properties_; + // Running count of death tests. + int death_test_count_; + // The elapsed time, in milliseconds. + TimeInMillis elapsed_time_; + + // We disallow copying TestResult. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestResult); +}; // class TestResult + +// A TestInfo object stores the following information about a test: +// +// Test case name +// Test name +// Whether the test should be run +// A function pointer that creates the test object when invoked +// Test result +// +// The constructor of TestInfo registers itself with the UnitTest +// singleton such that the RUN_ALL_TESTS() macro knows which tests to +// run. +class GTEST_API_ TestInfo { + public: + // Destructs a TestInfo object. This function is not virtual, so + // don't inherit from TestInfo. + ~TestInfo(); + + // Returns the test case name. + const char* test_case_name() const { return test_case_name_.c_str(); } + + // Returns the test name. + const char* name() const { return name_.c_str(); } + + // Returns the name of the parameter type, or NULL if this is not a typed + // or a type-parameterized test. + const char* type_param() const { + if (type_param_.get() != NULL) + return type_param_->c_str(); + return NULL; + } + + // Returns the text representation of the value parameter, or NULL if this + // is not a value-parameterized test. + const char* value_param() const { + if (value_param_.get() != NULL) + return value_param_->c_str(); + return NULL; + } + + // Returns true if this test should run, that is if the test is not + // disabled (or it is disabled but the also_run_disabled_tests flag has + // been specified) and its full name matches the user-specified filter. + // + // Google Test allows the user to filter the tests by their full names. + // The full name of a test Bar in test case Foo is defined as + // "Foo.Bar". Only the tests that match the filter will run. + // + // A filter is a colon-separated list of glob (not regex) patterns, + // optionally followed by a '-' and a colon-separated list of + // negative patterns (tests to exclude). A test is run if it + // matches one of the positive patterns and does not match any of + // the negative patterns. + // + // For example, *A*:Foo.* is a filter that matches any string that + // contains the character 'A' or starts with "Foo.". + bool should_run() const { return should_run_; } + + // Returns true iff this test will appear in the XML report. + bool is_reportable() const { + // For now, the XML report includes all tests matching the filter. + // In the future, we may trim tests that are excluded because of + // sharding. + return matches_filter_; + } + + // Returns the result of the test. + const TestResult* result() const { return &result_; } + + private: +#if GTEST_HAS_DEATH_TEST + friend class internal::DefaultDeathTestFactory; +#endif // GTEST_HAS_DEATH_TEST + friend class Test; + friend class TestCase; + friend class internal::UnitTestImpl; + friend class internal::StreamingListenerTest; + friend TestInfo* internal::MakeAndRegisterTestInfo( + const char* test_case_name, + const char* name, + const char* type_param, + const char* value_param, + internal::TypeId fixture_class_id, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc, + internal::TestFactoryBase* factory); + + // Constructs a TestInfo object. The newly constructed instance assumes + // ownership of the factory object. + TestInfo(const std::string& test_case_name, + const std::string& name, + const char* a_type_param, // NULL if not a type-parameterized test + const char* a_value_param, // NULL if not a value-parameterized test + internal::TypeId fixture_class_id, + internal::TestFactoryBase* factory); + + // Increments the number of death tests encountered in this test so + // far. + int increment_death_test_count() { + return result_.increment_death_test_count(); + } + + // Creates the test object, runs it, records its result, and then + // deletes it. + void Run(); + + static void ClearTestResult(TestInfo* test_info) { + test_info->result_.Clear(); + } + + // These fields are immutable properties of the test. + const std::string test_case_name_; // Test case name + const std::string name_; // Test name + // Name of the parameter type, or NULL if this is not a typed or a + // type-parameterized test. + const internal::scoped_ptr type_param_; + // Text representation of the value parameter, or NULL if this is not a + // value-parameterized test. + const internal::scoped_ptr value_param_; + const internal::TypeId fixture_class_id_; // ID of the test fixture class + bool should_run_; // True iff this test should run + bool is_disabled_; // True iff this test is disabled + bool matches_filter_; // True if this test matches the + // user-specified filter. + internal::TestFactoryBase* const factory_; // The factory that creates + // the test object + + // This field is mutable and needs to be reset before running the + // test for the second time. + TestResult result_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo); +}; + +// A test case, which consists of a vector of TestInfos. +// +// TestCase is not copyable. +class GTEST_API_ TestCase { + public: + // Creates a TestCase with the given name. + // + // TestCase does NOT have a default constructor. Always use this + // constructor to create a TestCase object. + // + // Arguments: + // + // name: name of the test case + // a_type_param: the name of the test's type parameter, or NULL if + // this is not a type-parameterized test. + // set_up_tc: pointer to the function that sets up the test case + // tear_down_tc: pointer to the function that tears down the test case + TestCase(const char* name, const char* a_type_param, + Test::SetUpTestCaseFunc set_up_tc, + Test::TearDownTestCaseFunc tear_down_tc); + + // Destructor of TestCase. + virtual ~TestCase(); + + // Gets the name of the TestCase. + const char* name() const { return name_.c_str(); } + + // Returns the name of the parameter type, or NULL if this is not a + // type-parameterized test case. + const char* type_param() const { + if (type_param_.get() != NULL) + return type_param_->c_str(); + return NULL; + } + + // Returns true if any test in this test case should run. + bool should_run() const { return should_run_; } + + // Gets the number of successful tests in this test case. + int successful_test_count() const; + + // Gets the number of failed tests in this test case. + int failed_test_count() const; + + // Gets the number of disabled tests that will be reported in the XML report. + int reportable_disabled_test_count() const; + + // Gets the number of disabled tests in this test case. + int disabled_test_count() const; + + // Gets the number of tests to be printed in the XML report. + int reportable_test_count() const; + + // Get the number of tests in this test case that should run. + int test_to_run_count() const; + + // Gets the number of all tests in this test case. + int total_test_count() const; + + // Returns true iff the test case passed. + bool Passed() const { return !Failed(); } + + // Returns true iff the test case failed. + bool Failed() const { return failed_test_count() > 0; } + + // Returns the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const { return elapsed_time_; } + + // Returns the i-th test among all the tests. i can range from 0 to + // total_test_count() - 1. If i is not in that range, returns NULL. + const TestInfo* GetTestInfo(int i) const; + + // Returns the TestResult that holds test properties recorded during + // execution of SetUpTestCase and TearDownTestCase. + const TestResult& ad_hoc_test_result() const { return ad_hoc_test_result_; } + + private: + friend class Test; + friend class internal::UnitTestImpl; + + // Gets the (mutable) vector of TestInfos in this TestCase. + std::vector& test_info_list() { return test_info_list_; } + + // Gets the (immutable) vector of TestInfos in this TestCase. + const std::vector& test_info_list() const { + return test_info_list_; + } + + // Returns the i-th test among all the tests. i can range from 0 to + // total_test_count() - 1. If i is not in that range, returns NULL. + TestInfo* GetMutableTestInfo(int i); + + // Sets the should_run member. + void set_should_run(bool should) { should_run_ = should; } + + // Adds a TestInfo to this test case. Will delete the TestInfo upon + // destruction of the TestCase object. + void AddTestInfo(TestInfo * test_info); + + // Clears the results of all tests in this test case. + void ClearResult(); + + // Clears the results of all tests in the given test case. + static void ClearTestCaseResult(TestCase* test_case) { + test_case->ClearResult(); + } + + // Runs every test in this TestCase. + void Run(); + + // Runs SetUpTestCase() for this TestCase. This wrapper is needed + // for catching exceptions thrown from SetUpTestCase(). + void RunSetUpTestCase() { (*set_up_tc_)(); } + + // Runs TearDownTestCase() for this TestCase. This wrapper is + // needed for catching exceptions thrown from TearDownTestCase(). + void RunTearDownTestCase() { (*tear_down_tc_)(); } + + // Returns true iff test passed. + static bool TestPassed(const TestInfo* test_info) { + return test_info->should_run() && test_info->result()->Passed(); + } + + // Returns true iff test failed. + static bool TestFailed(const TestInfo* test_info) { + return test_info->should_run() && test_info->result()->Failed(); + } + + // Returns true iff the test is disabled and will be reported in the XML + // report. + static bool TestReportableDisabled(const TestInfo* test_info) { + return test_info->is_reportable() && test_info->is_disabled_; + } + + // Returns true iff test is disabled. + static bool TestDisabled(const TestInfo* test_info) { + return test_info->is_disabled_; + } + + // Returns true iff this test will appear in the XML report. + static bool TestReportable(const TestInfo* test_info) { + return test_info->is_reportable(); + } + + // Returns true if the given test should run. + static bool ShouldRunTest(const TestInfo* test_info) { + return test_info->should_run(); + } + + // Shuffles the tests in this test case. + void ShuffleTests(internal::Random* random); + + // Restores the test order to before the first shuffle. + void UnshuffleTests(); + + // Name of the test case. + std::string name_; + // Name of the parameter type, or NULL if this is not a typed or a + // type-parameterized test. + const internal::scoped_ptr type_param_; + // The vector of TestInfos in their original order. It owns the + // elements in the vector. + std::vector test_info_list_; + // Provides a level of indirection for the test list to allow easy + // shuffling and restoring the test order. The i-th element in this + // vector is the index of the i-th test in the shuffled test list. + std::vector test_indices_; + // Pointer to the function that sets up the test case. + Test::SetUpTestCaseFunc set_up_tc_; + // Pointer to the function that tears down the test case. + Test::TearDownTestCaseFunc tear_down_tc_; + // True iff any test in this test case should run. + bool should_run_; + // Elapsed time, in milliseconds. + TimeInMillis elapsed_time_; + // Holds test properties recorded during execution of SetUpTestCase and + // TearDownTestCase. + TestResult ad_hoc_test_result_; + + // We disallow copying TestCases. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestCase); +}; + +// An Environment object is capable of setting up and tearing down an +// environment. The user should subclass this to define his own +// environment(s). +// +// An Environment object does the set-up and tear-down in virtual +// methods SetUp() and TearDown() instead of the constructor and the +// destructor, as: +// +// 1. You cannot safely throw from a destructor. This is a problem +// as in some cases Google Test is used where exceptions are enabled, and +// we may want to implement ASSERT_* using exceptions where they are +// available. +// 2. You cannot use ASSERT_* directly in a constructor or +// destructor. +class Environment { + public: + // The d'tor is virtual as we need to subclass Environment. + virtual ~Environment() {} + + // Override this to define how to set up the environment. + virtual void SetUp() {} + + // Override this to define how to tear down the environment. + virtual void TearDown() {} + private: + // If you see an error about overriding the following function or + // about it being private, you have mis-spelled SetUp() as Setup(). + struct Setup_should_be_spelled_SetUp {}; + virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; } +}; + +// The interface for tracing execution of tests. The methods are organized in +// the order the corresponding events are fired. +class TestEventListener { + public: + virtual ~TestEventListener() {} + + // Fired before any test activity starts. + virtual void OnTestProgramStart(const UnitTest& unit_test) = 0; + + // Fired before each iteration of tests starts. There may be more than + // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration + // index, starting from 0. + virtual void OnTestIterationStart(const UnitTest& unit_test, + int iteration) = 0; + + // Fired before environment set-up for each iteration of tests starts. + virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0; + + // Fired after environment set-up for each iteration of tests ends. + virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0; + + // Fired before the test case starts. + virtual void OnTestCaseStart(const TestCase& test_case) = 0; + + // Fired before the test starts. + virtual void OnTestStart(const TestInfo& test_info) = 0; + + // Fired after a failed assertion or a SUCCEED() invocation. + virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0; + + // Fired after the test ends. + virtual void OnTestEnd(const TestInfo& test_info) = 0; + + // Fired after the test case ends. + virtual void OnTestCaseEnd(const TestCase& test_case) = 0; + + // Fired before environment tear-down for each iteration of tests starts. + virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0; + + // Fired after environment tear-down for each iteration of tests ends. + virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0; + + // Fired after each iteration of tests finishes. + virtual void OnTestIterationEnd(const UnitTest& unit_test, + int iteration) = 0; + + // Fired after all test activities have ended. + virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0; +}; + +// The convenience class for users who need to override just one or two +// methods and are not concerned that a possible change to a signature of +// the methods they override will not be caught during the build. For +// comments about each method please see the definition of TestEventListener +// above. +class EmptyTestEventListener : public TestEventListener { + public: + virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationStart(const UnitTest& /*unit_test*/, + int /*iteration*/) {} + virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {} + virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestCaseStart(const TestCase& /*test_case*/) {} + virtual void OnTestStart(const TestInfo& /*test_info*/) {} + virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {} + virtual void OnTestEnd(const TestInfo& /*test_info*/) {} + virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {} + virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {} + virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/, + int /*iteration*/) {} + virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} +}; + +// TestEventListeners lets users add listeners to track events in Google Test. +class GTEST_API_ TestEventListeners { + public: + TestEventListeners(); + ~TestEventListeners(); + + // Appends an event listener to the end of the list. Google Test assumes + // the ownership of the listener (i.e. it will delete the listener when + // the test program finishes). + void Append(TestEventListener* listener); + + // Removes the given event listener from the list and returns it. It then + // becomes the caller's responsibility to delete the listener. Returns + // NULL if the listener is not found in the list. + TestEventListener* Release(TestEventListener* listener); + + // Returns the standard listener responsible for the default console + // output. Can be removed from the listeners list to shut down default + // console output. Note that removing this object from the listener list + // with Release transfers its ownership to the caller and makes this + // function return NULL the next time. + TestEventListener* default_result_printer() const { + return default_result_printer_; + } + + // Returns the standard listener responsible for the default XML output + // controlled by the --gtest_output=xml flag. Can be removed from the + // listeners list by users who want to shut down the default XML output + // controlled by this flag and substitute it with custom one. Note that + // removing this object from the listener list with Release transfers its + // ownership to the caller and makes this function return NULL the next + // time. + TestEventListener* default_xml_generator() const { + return default_xml_generator_; + } + + private: + friend class TestCase; + friend class TestInfo; + friend class internal::DefaultGlobalTestPartResultReporter; + friend class internal::NoExecDeathTest; + friend class internal::TestEventListenersAccessor; + friend class internal::UnitTestImpl; + + // Returns repeater that broadcasts the TestEventListener events to all + // subscribers. + TestEventListener* repeater(); + + // Sets the default_result_printer attribute to the provided listener. + // The listener is also added to the listener list and previous + // default_result_printer is removed from it and deleted. The listener can + // also be NULL in which case it will not be added to the list. Does + // nothing if the previous and the current listener objects are the same. + void SetDefaultResultPrinter(TestEventListener* listener); + + // Sets the default_xml_generator attribute to the provided listener. The + // listener is also added to the listener list and previous + // default_xml_generator is removed from it and deleted. The listener can + // also be NULL in which case it will not be added to the list. Does + // nothing if the previous and the current listener objects are the same. + void SetDefaultXmlGenerator(TestEventListener* listener); + + // Controls whether events will be forwarded by the repeater to the + // listeners in the list. + bool EventForwardingEnabled() const; + void SuppressEventForwarding(); + + // The actual list of listeners. + internal::TestEventRepeater* repeater_; + // Listener responsible for the standard result output. + TestEventListener* default_result_printer_; + // Listener responsible for the creation of the XML output file. + TestEventListener* default_xml_generator_; + + // We disallow copying TestEventListeners. + GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventListeners); +}; + +// A UnitTest consists of a vector of TestCases. +// +// This is a singleton class. The only instance of UnitTest is +// created when UnitTest::GetInstance() is first called. This +// instance is never deleted. +// +// UnitTest is not copyable. +// +// This class is thread-safe as long as the methods are called +// according to their specification. +class GTEST_API_ UnitTest { + public: + // Gets the singleton UnitTest object. The first time this method + // is called, a UnitTest object is constructed and returned. + // Consecutive calls will return the same object. + static UnitTest* GetInstance(); + + // Runs all tests in this UnitTest object and prints the result. + // Returns 0 if successful, or 1 otherwise. + // + // This method can only be called from the main thread. + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + int Run() GTEST_MUST_USE_RESULT_; + + // Returns the working directory when the first TEST() or TEST_F() + // was executed. The UnitTest object owns the string. + const char* original_working_dir() const; + + // Returns the TestCase object for the test that's currently running, + // or NULL if no test is running. + const TestCase* current_test_case() const + GTEST_LOCK_EXCLUDED_(mutex_); + + // Returns the TestInfo object for the test that's currently running, + // or NULL if no test is running. + const TestInfo* current_test_info() const + GTEST_LOCK_EXCLUDED_(mutex_); + + // Returns the random seed used at the start of the current test run. + int random_seed() const; + +#if GTEST_HAS_PARAM_TEST + // Returns the ParameterizedTestCaseRegistry object used to keep track of + // value-parameterized tests and instantiate and register them. + // + // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + internal::ParameterizedTestCaseRegistry& parameterized_test_registry() + GTEST_LOCK_EXCLUDED_(mutex_); +#endif // GTEST_HAS_PARAM_TEST + + // Gets the number of successful test cases. + int successful_test_case_count() const; + + // Gets the number of failed test cases. + int failed_test_case_count() const; + + // Gets the number of all test cases. + int total_test_case_count() const; + + // Gets the number of all test cases that contain at least one test + // that should run. + int test_case_to_run_count() const; + + // Gets the number of successful tests. + int successful_test_count() const; + + // Gets the number of failed tests. + int failed_test_count() const; + + // Gets the number of disabled tests that will be reported in the XML report. + int reportable_disabled_test_count() const; + + // Gets the number of disabled tests. + int disabled_test_count() const; + + // Gets the number of tests to be printed in the XML report. + int reportable_test_count() const; + + // Gets the number of all tests. + int total_test_count() const; + + // Gets the number of tests that should run. + int test_to_run_count() const; + + // Gets the time of the test program start, in ms from the start of the + // UNIX epoch. + TimeInMillis start_timestamp() const; + + // Gets the elapsed time, in milliseconds. + TimeInMillis elapsed_time() const; + + // Returns true iff the unit test passed (i.e. all test cases passed). + bool Passed() const; + + // Returns true iff the unit test failed (i.e. some test case failed + // or something outside of all tests failed). + bool Failed() const; + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + const TestCase* GetTestCase(int i) const; + + // Returns the TestResult containing information on test failures and + // properties logged outside of individual test cases. + const TestResult& ad_hoc_test_result() const; + + // Returns the list of event listeners that can be used to track events + // inside Google Test. + TestEventListeners& listeners(); + + private: + // Registers and returns a global test environment. When a test + // program is run, all global test environments will be set-up in + // the order they were registered. After all tests in the program + // have finished, all global test environments will be torn-down in + // the *reverse* order they were registered. + // + // The UnitTest object takes ownership of the given environment. + // + // This method can only be called from the main thread. + Environment* AddEnvironment(Environment* env); + + // Adds a TestPartResult to the current TestResult object. All + // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) + // eventually call this to report their results. The user code + // should use the assertion macros instead of calling this directly. + void AddTestPartResult(TestPartResult::Type result_type, + const char* file_name, + int line_number, + const std::string& message, + const std::string& os_stack_trace) + GTEST_LOCK_EXCLUDED_(mutex_); + + // Adds a TestProperty to the current TestResult object when invoked from + // inside a test, to current TestCase's ad_hoc_test_result_ when invoked + // from SetUpTestCase or TearDownTestCase, or to the global property set + // when invoked elsewhere. If the result already contains a property with + // the same key, the value will be updated. + void RecordProperty(const std::string& key, const std::string& value); + + // Gets the i-th test case among all the test cases. i can range from 0 to + // total_test_case_count() - 1. If i is not in that range, returns NULL. + TestCase* GetMutableTestCase(int i); + + // Accessors for the implementation object. + internal::UnitTestImpl* impl() { return impl_; } + const internal::UnitTestImpl* impl() const { return impl_; } + + // These classes and funcions are friends as they need to access private + // members of UnitTest. + friend class Test; + friend class internal::AssertHelper; + friend class internal::ScopedTrace; + friend class internal::StreamingListenerTest; + friend class internal::UnitTestRecordPropertyTestHelper; + friend Environment* AddGlobalTestEnvironment(Environment* env); + friend internal::UnitTestImpl* internal::GetUnitTestImpl(); + friend void internal::ReportFailureInUnknownLocation( + TestPartResult::Type result_type, + const std::string& message); + + // Creates an empty UnitTest. + UnitTest(); + + // D'tor + virtual ~UnitTest(); + + // Pushes a trace defined by SCOPED_TRACE() on to the per-thread + // Google Test trace stack. + void PushGTestTrace(const internal::TraceInfo& trace) + GTEST_LOCK_EXCLUDED_(mutex_); + + // Pops a trace from the per-thread Google Test trace stack. + void PopGTestTrace() + GTEST_LOCK_EXCLUDED_(mutex_); + + // Protects mutable state in *impl_. This is mutable as some const + // methods need to lock it too. + mutable internal::Mutex mutex_; + + // Opaque implementation object. This field is never changed once + // the object is constructed. We don't mark it as const here, as + // doing so will cause a warning in the constructor of UnitTest. + // Mutable state in *impl_ is protected by mutex_. + internal::UnitTestImpl* impl_; + + // We disallow copying UnitTest. + GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTest); +}; + +// A convenient wrapper for adding an environment for the test +// program. +// +// You should call this before RUN_ALL_TESTS() is called, probably in +// main(). If you use gtest_main, you need to call this before main() +// starts for it to take effect. For example, you can define a global +// variable like this: +// +// testing::Environment* const foo_env = +// testing::AddGlobalTestEnvironment(new FooEnvironment); +// +// However, we strongly recommend you to write your own main() and +// call AddGlobalTestEnvironment() there, as relying on initialization +// of global variables makes the code harder to read and may cause +// problems when you register multiple environments from different +// translation units and the environments have dependencies among them +// (remember that the compiler doesn't guarantee the order in which +// global variables from different translation units are initialized). +inline Environment* AddGlobalTestEnvironment(Environment* env) { + return UnitTest::GetInstance()->AddEnvironment(env); +} + +// Initializes Google Test. This must be called before calling +// RUN_ALL_TESTS(). In particular, it parses a command line for the +// flags that Google Test recognizes. Whenever a Google Test flag is +// seen, it is removed from argv, and *argc is decremented. +// +// No value is returned. Instead, the Google Test flag variables are +// updated. +// +// Calling the function for the second time has no user-visible effect. +GTEST_API_ void InitGoogleTest(int* argc, char** argv); + +// This overloaded version can be used in Windows programs compiled in +// UNICODE mode. +GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv); + +namespace internal { + +// FormatForComparison::Format(value) formats a +// value of type ToPrint that is an operand of a comparison assertion +// (e.g. ASSERT_EQ). OtherOperand is the type of the other operand in +// the comparison, and is used to help determine the best way to +// format the value. In particular, when the value is a C string +// (char pointer) and the other operand is an STL string object, we +// want to format the C string as a string, since we know it is +// compared by value with the string object. If the value is a char +// pointer but the other operand is not an STL string object, we don't +// know whether the pointer is supposed to point to a NUL-terminated +// string, and thus want to print it as a pointer to be safe. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + +// The default case. +template +class FormatForComparison { + public: + static ::std::string Format(const ToPrint& value) { + return ::testing::PrintToString(value); + } +}; + +// Array. +template +class FormatForComparison { + public: + static ::std::string Format(const ToPrint* value) { + return FormatForComparison::Format(value); + } +}; + +// By default, print C string as pointers to be safe, as we don't know +// whether they actually point to a NUL-terminated string. + +#define GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(CharType) \ + template \ + class FormatForComparison { \ + public: \ + static ::std::string Format(CharType* value) { \ + return ::testing::PrintToString(static_cast(value)); \ + } \ + } + +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t); + +#undef GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_ + +// If a C string is compared with an STL string object, we know it's meant +// to point to a NUL-terminated string, and thus can print it as a string. + +#define GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(CharType, OtherStringType) \ + template <> \ + class FormatForComparison { \ + public: \ + static ::std::string Format(CharType* value) { \ + return ::testing::PrintToString(value); \ + } \ + } + +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string); + +#if GTEST_HAS_GLOBAL_STRING +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::string); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::string); +#endif + +#if GTEST_HAS_GLOBAL_WSTRING +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::wstring); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::wstring); +#endif + +#if GTEST_HAS_STD_WSTRING +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring); +#endif + +#undef GTEST_IMPL_FORMAT_C_STRING_AS_STRING_ + +// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc) +// operand to be used in a failure message. The type (but not value) +// of the other operand may affect the format. This allows us to +// print a char* as a raw pointer when it is compared against another +// char* or void*, and print it as a C string when it is compared +// against an std::string object, for example. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +template +std::string FormatForComparisonFailureMessage( + const T1& value, const T2& /* other_operand */) { + return FormatForComparison::Format(value); +} + +// The helper function for {ASSERT|EXPECT}_EQ. +template +AssertionResult CmpHelperEQ(const char* expected_expression, + const char* actual_expression, + const T1& expected, + const T2& actual) { +#ifdef _MSC_VER +# pragma warning(push) // Saves the current warning state. +# pragma warning(disable:4389) // Temporarily disables warning on + // signed/unsigned mismatch. +#endif + + if (expected == actual) { + return AssertionSuccess(); + } + +#ifdef _MSC_VER +# pragma warning(pop) // Restores the warning state. +#endif + + return EqFailure(expected_expression, + actual_expression, + FormatForComparisonFailureMessage(expected, actual), + FormatForComparisonFailureMessage(actual, expected), + false); +} + +// With this overloaded version, we allow anonymous enums to be used +// in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums +// can be implicitly cast to BiggestInt. +GTEST_API_ AssertionResult CmpHelperEQ(const char* expected_expression, + const char* actual_expression, + BiggestInt expected, + BiggestInt actual); + +// The helper class for {ASSERT|EXPECT}_EQ. The template argument +// lhs_is_null_literal is true iff the first argument to ASSERT_EQ() +// is a null pointer literal. The following default implementation is +// for lhs_is_null_literal being false. +template +class EqHelper { + public: + // This templatized version is for the general case. + template + static AssertionResult Compare(const char* expected_expression, + const char* actual_expression, + const T1& expected, + const T2& actual) { + return CmpHelperEQ(expected_expression, actual_expression, expected, + actual); + } + + // With this overloaded version, we allow anonymous enums to be used + // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous + // enums can be implicitly cast to BiggestInt. + // + // Even though its body looks the same as the above version, we + // cannot merge the two, as it will make anonymous enums unhappy. + static AssertionResult Compare(const char* expected_expression, + const char* actual_expression, + BiggestInt expected, + BiggestInt actual) { + return CmpHelperEQ(expected_expression, actual_expression, expected, + actual); + } +}; + +// This specialization is used when the first argument to ASSERT_EQ() +// is a null pointer literal, like NULL, false, or 0. +template <> +class EqHelper { + public: + // We define two overloaded versions of Compare(). The first + // version will be picked when the second argument to ASSERT_EQ() is + // NOT a pointer, e.g. ASSERT_EQ(0, AnIntFunction()) or + // EXPECT_EQ(false, a_bool). + template + static AssertionResult Compare( + const char* expected_expression, + const char* actual_expression, + const T1& expected, + const T2& actual, + // The following line prevents this overload from being considered if T2 + // is not a pointer type. We need this because ASSERT_EQ(NULL, my_ptr) + // expands to Compare("", "", NULL, my_ptr), which requires a conversion + // to match the Secret* in the other overload, which would otherwise make + // this template match better. + typename EnableIf::value>::type* = 0) { + return CmpHelperEQ(expected_expression, actual_expression, expected, + actual); + } + + // This version will be picked when the second argument to ASSERT_EQ() is a + // pointer, e.g. ASSERT_EQ(NULL, a_pointer). + template + static AssertionResult Compare( + const char* expected_expression, + const char* actual_expression, + // We used to have a second template parameter instead of Secret*. That + // template parameter would deduce to 'long', making this a better match + // than the first overload even without the first overload's EnableIf. + // Unfortunately, gcc with -Wconversion-null warns when "passing NULL to + // non-pointer argument" (even a deduced integral argument), so the old + // implementation caused warnings in user code. + Secret* /* expected (NULL) */, + T* actual) { + // We already know that 'expected' is a null pointer. + return CmpHelperEQ(expected_expression, actual_expression, + static_cast(NULL), actual); + } +}; + +// A macro for implementing the helper functions needed to implement +// ASSERT_?? and EXPECT_??. It is here just to avoid copy-and-paste +// of similar code. +// +// For each templatized helper function, we also define an overloaded +// version for BiggestInt in order to reduce code bloat and allow +// anonymous enums to be used with {ASSERT|EXPECT}_?? when compiled +// with gcc 4. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +#define GTEST_IMPL_CMP_HELPER_(op_name, op)\ +template \ +AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ + const T1& val1, const T2& val2) {\ + if (val1 op val2) {\ + return AssertionSuccess();\ + } else {\ + return AssertionFailure() \ + << "Expected: (" << expr1 << ") " #op " (" << expr2\ + << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\ + << " vs " << FormatForComparisonFailureMessage(val2, val1);\ + }\ +}\ +GTEST_API_ AssertionResult CmpHelper##op_name(\ + const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2) + +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. + +// Implements the helper function for {ASSERT|EXPECT}_NE +GTEST_IMPL_CMP_HELPER_(NE, !=); +// Implements the helper function for {ASSERT|EXPECT}_LE +GTEST_IMPL_CMP_HELPER_(LE, <=); +// Implements the helper function for {ASSERT|EXPECT}_LT +GTEST_IMPL_CMP_HELPER_(LT, <); +// Implements the helper function for {ASSERT|EXPECT}_GE +GTEST_IMPL_CMP_HELPER_(GE, >=); +// Implements the helper function for {ASSERT|EXPECT}_GT +GTEST_IMPL_CMP_HELPER_(GT, >); + +#undef GTEST_IMPL_CMP_HELPER_ + +// The helper function for {ASSERT|EXPECT}_STREQ. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual); + +// The helper function for {ASSERT|EXPECT}_STRCASEEQ. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression, + const char* actual_expression, + const char* expected, + const char* actual); + +// The helper function for {ASSERT|EXPECT}_STRNE. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2); + +// The helper function for {ASSERT|EXPECT}_STRCASENE. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression, + const char* s2_expression, + const char* s1, + const char* s2); + + +// Helper function for *_STREQ on wide strings. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression, + const char* actual_expression, + const wchar_t* expected, + const wchar_t* actual); + +// Helper function for *_STRNE on wide strings. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression, + const char* s2_expression, + const wchar_t* s1, + const wchar_t* s2); + +} // namespace internal + +// IsSubstring() and IsNotSubstring() are intended to be used as the +// first argument to {EXPECT,ASSERT}_PRED_FORMAT2(), not by +// themselves. They check whether needle is a substring of haystack +// (NULL is considered a substring of itself only), and return an +// appropriate error message when they fail. +// +// The {needle,haystack}_expr arguments are the stringified +// expressions that generated the two real arguments. +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack); +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const char* needle, const char* haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const wchar_t* needle, const wchar_t* haystack); +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::string& needle, const ::std::string& haystack); + +#if GTEST_HAS_STD_WSTRING +GTEST_API_ AssertionResult IsSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack); +GTEST_API_ AssertionResult IsNotSubstring( + const char* needle_expr, const char* haystack_expr, + const ::std::wstring& needle, const ::std::wstring& haystack); +#endif // GTEST_HAS_STD_WSTRING + +namespace internal { + +// Helper template function for comparing floating-points. +// +// Template parameter: +// +// RawType: the raw floating-point type (either float or double) +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +template +AssertionResult CmpHelperFloatingPointEQ(const char* expected_expression, + const char* actual_expression, + RawType expected, + RawType actual) { + const FloatingPoint lhs(expected), rhs(actual); + + if (lhs.AlmostEquals(rhs)) { + return AssertionSuccess(); + } + + ::std::stringstream expected_ss; + expected_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << expected; + + ::std::stringstream actual_ss; + actual_ss << std::setprecision(std::numeric_limits::digits10 + 2) + << actual; + + return EqFailure(expected_expression, + actual_expression, + StringStreamToString(&expected_ss), + StringStreamToString(&actual_ss), + false); +} + +// Helper function for implementing ASSERT_NEAR. +// +// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. +GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1, + const char* expr2, + const char* abs_error_expr, + double val1, + double val2, + double abs_error); + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// A class that enables one to stream messages to assertion macros +class GTEST_API_ AssertHelper { + public: + // Constructor. + AssertHelper(TestPartResult::Type type, + const char* file, + int line, + const char* message); + ~AssertHelper(); + + // Message assignment is a semantic trick to enable assertion + // streaming; see the GTEST_MESSAGE_ macro below. + void operator=(const Message& message) const; + + private: + // We put our data in a struct so that the size of the AssertHelper class can + // be as small as possible. This is important because gcc is incapable of + // re-using stack space even for temporary variables, so every EXPECT_EQ + // reserves stack space for another AssertHelper. + struct AssertHelperData { + AssertHelperData(TestPartResult::Type t, + const char* srcfile, + int line_num, + const char* msg) + : type(t), file(srcfile), line(line_num), message(msg) { } + + TestPartResult::Type const type; + const char* const file; + int const line; + std::string const message; + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData); + }; + + AssertHelperData* const data_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper); +}; + +} // namespace internal + +#if GTEST_HAS_PARAM_TEST +// The pure interface class that all value-parameterized tests inherit from. +// A value-parameterized class must inherit from both ::testing::Test and +// ::testing::WithParamInterface. In most cases that just means inheriting +// from ::testing::TestWithParam, but more complicated test hierarchies +// may need to inherit from Test and WithParamInterface at different levels. +// +// This interface has support for accessing the test parameter value via +// the GetParam() method. +// +// Use it with one of the parameter generator defining functions, like Range(), +// Values(), ValuesIn(), Bool(), and Combine(). +// +// class FooTest : public ::testing::TestWithParam { +// protected: +// FooTest() { +// // Can use GetParam() here. +// } +// virtual ~FooTest() { +// // Can use GetParam() here. +// } +// virtual void SetUp() { +// // Can use GetParam() here. +// } +// virtual void TearDown { +// // Can use GetParam() here. +// } +// }; +// TEST_P(FooTest, DoesBar) { +// // Can use GetParam() method here. +// Foo foo; +// ASSERT_TRUE(foo.DoesBar(GetParam())); +// } +// INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10)); + +template +class WithParamInterface { + public: + typedef T ParamType; + virtual ~WithParamInterface() {} + + // The current parameter value. Is also available in the test fixture's + // constructor. This member function is non-static, even though it only + // references static data, to reduce the opportunity for incorrect uses + // like writing 'WithParamInterface::GetParam()' for a test that + // uses a fixture whose parameter type is int. + const ParamType& GetParam() const { + GTEST_CHECK_(parameter_ != NULL) + << "GetParam() can only be called inside a value-parameterized test " + << "-- did you intend to write TEST_P instead of TEST_F?"; + return *parameter_; + } + + private: + // Sets parameter value. The caller is responsible for making sure the value + // remains alive and unchanged throughout the current test. + static void SetParam(const ParamType* parameter) { + parameter_ = parameter; + } + + // Static value used for accessing parameter during a test lifetime. + static const ParamType* parameter_; + + // TestClass must be a subclass of WithParamInterface and Test. + template friend class internal::ParameterizedTestFactory; +}; + +template +const T* WithParamInterface::parameter_ = NULL; + +// Most value-parameterized classes can ignore the existence of +// WithParamInterface, and can just inherit from ::testing::TestWithParam. + +template +class TestWithParam : public Test, public WithParamInterface { +}; + +#endif // GTEST_HAS_PARAM_TEST + +// Macros for indicating success/failure in test code. + +// ADD_FAILURE unconditionally adds a failure to the current test. +// SUCCEED generates a success - it doesn't automatically make the +// current test successful, as a test is only successful when it has +// no failure. +// +// EXPECT_* verifies that a certain condition is satisfied. If not, +// it behaves like ADD_FAILURE. In particular: +// +// EXPECT_TRUE verifies that a Boolean condition is true. +// EXPECT_FALSE verifies that a Boolean condition is false. +// +// FAIL and ASSERT_* are similar to ADD_FAILURE and EXPECT_*, except +// that they will also abort the current function on failure. People +// usually want the fail-fast behavior of FAIL and ASSERT_*, but those +// writing data-driven tests often find themselves using ADD_FAILURE +// and EXPECT_* more. + +// Generates a nonfatal failure with a generic message. +#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed") + +// Generates a nonfatal failure at the given source file location with +// a generic message. +#define ADD_FAILURE_AT(file, line) \ + GTEST_MESSAGE_AT_(file, line, "Failed", \ + ::testing::TestPartResult::kNonFatalFailure) + +// Generates a fatal failure with a generic message. +#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed") + +// Define this macro to 1 to omit the definition of FAIL(), which is a +// generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_FAIL +# define FAIL() GTEST_FAIL() +#endif + +// Generates a success with a generic message. +#define GTEST_SUCCEED() GTEST_SUCCESS_("Succeeded") + +// Define this macro to 1 to omit the definition of SUCCEED(), which +// is a generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_SUCCEED +# define SUCCEED() GTEST_SUCCEED() +#endif + +// Macros for testing exceptions. +// +// * {ASSERT|EXPECT}_THROW(statement, expected_exception): +// Tests that the statement throws the expected exception. +// * {ASSERT|EXPECT}_NO_THROW(statement): +// Tests that the statement doesn't throw any exception. +// * {ASSERT|EXPECT}_ANY_THROW(statement): +// Tests that the statement throws an exception. + +#define EXPECT_THROW(statement, expected_exception) \ + GTEST_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_) +#define EXPECT_NO_THROW(statement) \ + GTEST_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_) +#define EXPECT_ANY_THROW(statement) \ + GTEST_TEST_ANY_THROW_(statement, GTEST_NONFATAL_FAILURE_) +#define ASSERT_THROW(statement, expected_exception) \ + GTEST_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_) +#define ASSERT_NO_THROW(statement) \ + GTEST_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_) +#define ASSERT_ANY_THROW(statement) \ + GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_) + +// Boolean assertions. Condition can be either a Boolean expression or an +// AssertionResult. For more information on how to use AssertionResult with +// these macros see comments on that class. +#define EXPECT_TRUE(condition) \ + GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ + GTEST_NONFATAL_FAILURE_) +#define EXPECT_FALSE(condition) \ + GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ + GTEST_NONFATAL_FAILURE_) +#define ASSERT_TRUE(condition) \ + GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ + GTEST_FATAL_FAILURE_) +#define ASSERT_FALSE(condition) \ + GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ + GTEST_FATAL_FAILURE_) + +// Includes the auto-generated header that implements a family of +// generic predicate assertion macros. +// Copyright 2006, 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. + +// This file is AUTOMATICALLY GENERATED on 10/31/2011 by command +// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND! +// +// Implements a family of generic predicate assertion macros. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ +#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ + +// Makes sure this header is not included before gtest.h. +#ifndef GTEST_INCLUDE_GTEST_GTEST_H_ +# error Do not include gtest_pred_impl.h directly. Include gtest.h instead. +#endif // GTEST_INCLUDE_GTEST_GTEST_H_ + +// This header implements a family of generic predicate assertion +// macros: +// +// ASSERT_PRED_FORMAT1(pred_format, v1) +// ASSERT_PRED_FORMAT2(pred_format, v1, v2) +// ... +// +// where pred_format is a function or functor that takes n (in the +// case of ASSERT_PRED_FORMATn) values and their source expression +// text, and returns a testing::AssertionResult. See the definition +// of ASSERT_EQ in gtest.h for an example. +// +// If you don't care about formatting, you can use the more +// restrictive version: +// +// ASSERT_PRED1(pred, v1) +// ASSERT_PRED2(pred, v1, v2) +// ... +// +// where pred is an n-ary function or functor that returns bool, +// and the values v1, v2, ..., must support the << operator for +// streaming to std::ostream. +// +// We also define the EXPECT_* variations. +// +// For now we only support predicates whose arity is at most 5. +// Please email googletestframework@googlegroups.com if you need +// support for higher arities. + +// GTEST_ASSERT_ is the basic statement to which all of the assertions +// in this file reduce. Don't use this in your code. + +#define GTEST_ASSERT_(expression, on_failure) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (const ::testing::AssertionResult gtest_ar = (expression)) \ + ; \ + else \ + on_failure(gtest_ar.failure_message()) + + +// Helper function for implementing {EXPECT|ASSERT}_PRED1. Don't use +// this in your code. +template +AssertionResult AssertPred1Helper(const char* pred_text, + const char* e1, + Pred pred, + const T1& v1) { + if (pred(v1)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1. +// Don't use this in your code. +#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, v1), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED1. Don't use +// this in your code. +#define GTEST_PRED1_(pred, v1, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \ + #v1, \ + pred, \ + v1), on_failure) + +// Unary predicate assertion macros. +#define EXPECT_PRED_FORMAT1(pred_format, v1) \ + GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED1(pred, v1) \ + GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT1(pred_format, v1) \ + GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED1(pred, v1) \ + GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED2. Don't use +// this in your code. +template +AssertionResult AssertPred2Helper(const char* pred_text, + const char* e1, + const char* e2, + Pred pred, + const T1& v1, + const T2& v2) { + if (pred(v1, v2)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2. +// Don't use this in your code. +#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED2. Don't use +// this in your code. +#define GTEST_PRED2_(pred, v1, v2, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \ + #v1, \ + #v2, \ + pred, \ + v1, \ + v2), on_failure) + +// Binary predicate assertion macros. +#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \ + GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED2(pred, v1, v2) \ + GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \ + GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED2(pred, v1, v2) \ + GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED3. Don't use +// this in your code. +template +AssertionResult AssertPred3Helper(const char* pred_text, + const char* e1, + const char* e2, + const char* e3, + Pred pred, + const T1& v1, + const T2& v2, + const T3& v3) { + if (pred(v1, v2, v3)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ", " + << e3 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2 + << "\n" << e3 << " evaluates to " << v3; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3. +// Don't use this in your code. +#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED3. Don't use +// this in your code. +#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \ + #v1, \ + #v2, \ + #v3, \ + pred, \ + v1, \ + v2, \ + v3), on_failure) + +// Ternary predicate assertion macros. +#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \ + GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED3(pred, v1, v2, v3) \ + GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \ + GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED3(pred, v1, v2, v3) \ + GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED4. Don't use +// this in your code. +template +AssertionResult AssertPred4Helper(const char* pred_text, + const char* e1, + const char* e2, + const char* e3, + const char* e4, + Pred pred, + const T1& v1, + const T2& v2, + const T3& v3, + const T4& v4) { + if (pred(v1, v2, v3, v4)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ", " + << e3 << ", " + << e4 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2 + << "\n" << e3 << " evaluates to " << v3 + << "\n" << e4 << " evaluates to " << v4; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4. +// Don't use this in your code. +#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED4. Don't use +// this in your code. +#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \ + #v1, \ + #v2, \ + #v3, \ + #v4, \ + pred, \ + v1, \ + v2, \ + v3, \ + v4), on_failure) + +// 4-ary predicate assertion macros. +#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \ + GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED4(pred, v1, v2, v3, v4) \ + GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \ + GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED4(pred, v1, v2, v3, v4) \ + GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_) + + + +// Helper function for implementing {EXPECT|ASSERT}_PRED5. Don't use +// this in your code. +template +AssertionResult AssertPred5Helper(const char* pred_text, + const char* e1, + const char* e2, + const char* e3, + const char* e4, + const char* e5, + Pred pred, + const T1& v1, + const T2& v2, + const T3& v3, + const T4& v4, + const T5& v5) { + if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess(); + + return AssertionFailure() << pred_text << "(" + << e1 << ", " + << e2 << ", " + << e3 << ", " + << e4 << ", " + << e5 << ") evaluates to false, where" + << "\n" << e1 << " evaluates to " << v1 + << "\n" << e2 << " evaluates to " << v2 + << "\n" << e3 << " evaluates to " << v3 + << "\n" << e4 << " evaluates to " << v4 + << "\n" << e5 << " evaluates to " << v5; +} + +// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5. +// Don't use this in your code. +#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\ + GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5), \ + on_failure) + +// Internal macro for implementing {EXPECT|ASSERT}_PRED5. Don't use +// this in your code. +#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\ + GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \ + #v1, \ + #v2, \ + #v3, \ + #v4, \ + #v5, \ + pred, \ + v1, \ + v2, \ + v3, \ + v4, \ + v5), on_failure) + +// 5-ary predicate assertion macros. +#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \ + GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_) +#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \ + GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_) +#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \ + GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_) +#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \ + GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_) + + + +#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ + +// Macros for testing equalities and inequalities. +// +// * {ASSERT|EXPECT}_EQ(expected, actual): Tests that expected == actual +// * {ASSERT|EXPECT}_NE(v1, v2): Tests that v1 != v2 +// * {ASSERT|EXPECT}_LT(v1, v2): Tests that v1 < v2 +// * {ASSERT|EXPECT}_LE(v1, v2): Tests that v1 <= v2 +// * {ASSERT|EXPECT}_GT(v1, v2): Tests that v1 > v2 +// * {ASSERT|EXPECT}_GE(v1, v2): Tests that v1 >= v2 +// +// When they are not, Google Test prints both the tested expressions and +// their actual values. The values must be compatible built-in types, +// or you will get a compiler error. By "compatible" we mean that the +// values can be compared by the respective operator. +// +// Note: +// +// 1. It is possible to make a user-defined type work with +// {ASSERT|EXPECT}_??(), but that requires overloading the +// comparison operators and is thus discouraged by the Google C++ +// Usage Guide. Therefore, you are advised to use the +// {ASSERT|EXPECT}_TRUE() macro to assert that two objects are +// equal. +// +// 2. The {ASSERT|EXPECT}_??() macros do pointer comparisons on +// pointers (in particular, C strings). Therefore, if you use it +// with two C strings, you are testing how their locations in memory +// are related, not how their content is related. To compare two C +// strings by content, use {ASSERT|EXPECT}_STR*(). +// +// 3. {ASSERT|EXPECT}_EQ(expected, actual) is preferred to +// {ASSERT|EXPECT}_TRUE(expected == actual), as the former tells you +// what the actual value is when it fails, and similarly for the +// other comparisons. +// +// 4. Do not depend on the order in which {ASSERT|EXPECT}_??() +// evaluate their arguments, which is undefined. +// +// 5. These macros evaluate their arguments exactly once. +// +// Examples: +// +// EXPECT_NE(5, Foo()); +// EXPECT_EQ(NULL, a_pointer); +// ASSERT_LT(i, array_size); +// ASSERT_GT(records.size(), 0) << "There is no record left."; + +#define EXPECT_EQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal:: \ + EqHelper::Compare, \ + expected, actual) +#define EXPECT_NE(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, expected, actual) +#define EXPECT_LE(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2) +#define EXPECT_LT(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2) +#define EXPECT_GE(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2) +#define EXPECT_GT(val1, val2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2) + +#define GTEST_ASSERT_EQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::testing::internal:: \ + EqHelper::Compare, \ + expected, actual) +#define GTEST_ASSERT_NE(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2) +#define GTEST_ASSERT_LE(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2) +#define GTEST_ASSERT_LT(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2) +#define GTEST_ASSERT_GE(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2) +#define GTEST_ASSERT_GT(val1, val2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2) + +// Define macro GTEST_DONT_DEFINE_ASSERT_XY to 1 to omit the definition of +// ASSERT_XY(), which clashes with some users' own code. + +#if !GTEST_DONT_DEFINE_ASSERT_EQ +# define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_NE +# define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_LE +# define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_LT +# define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_GE +# define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_GT +# define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2) +#endif + +// C-string Comparisons. All tests treat NULL and any non-NULL string +// as different. Two NULLs are equal. +// +// * {ASSERT|EXPECT}_STREQ(s1, s2): Tests that s1 == s2 +// * {ASSERT|EXPECT}_STRNE(s1, s2): Tests that s1 != s2 +// * {ASSERT|EXPECT}_STRCASEEQ(s1, s2): Tests that s1 == s2, ignoring case +// * {ASSERT|EXPECT}_STRCASENE(s1, s2): Tests that s1 != s2, ignoring case +// +// For wide or narrow string objects, you can use the +// {ASSERT|EXPECT}_??() macros. +// +// Don't depend on the order in which the arguments are evaluated, +// which is undefined. +// +// These macros evaluate their arguments exactly once. + +#define EXPECT_STREQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual) +#define EXPECT_STRNE(s1, s2) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2) +#define EXPECT_STRCASEEQ(expected, actual) \ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual) +#define EXPECT_STRCASENE(s1, s2)\ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2) + +#define ASSERT_STREQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual) +#define ASSERT_STRNE(s1, s2) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2) +#define ASSERT_STRCASEEQ(expected, actual) \ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual) +#define ASSERT_STRCASENE(s1, s2)\ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2) + +// Macros for comparing floating-point numbers. +// +// * {ASSERT|EXPECT}_FLOAT_EQ(expected, actual): +// Tests that two float values are almost equal. +// * {ASSERT|EXPECT}_DOUBLE_EQ(expected, actual): +// Tests that two double values are almost equal. +// * {ASSERT|EXPECT}_NEAR(v1, v2, abs_error): +// Tests that v1 and v2 are within the given distance to each other. +// +// Google Test uses ULP-based comparison to automatically pick a default +// error bound that is appropriate for the operands. See the +// FloatingPoint template class in gtest-internal.h if you are +// interested in the implementation details. + +#define EXPECT_FLOAT_EQ(expected, actual)\ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define EXPECT_DOUBLE_EQ(expected, actual)\ + EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define ASSERT_FLOAT_EQ(expected, actual)\ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define ASSERT_DOUBLE_EQ(expected, actual)\ + ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ + expected, actual) + +#define EXPECT_NEAR(val1, val2, abs_error)\ + EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \ + val1, val2, abs_error) + +#define ASSERT_NEAR(val1, val2, abs_error)\ + ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \ + val1, val2, abs_error) + +// These predicate format functions work on floating-point values, and +// can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g. +// +// EXPECT_PRED_FORMAT2(testing::DoubleLE, Foo(), 5.0); + +// Asserts that val1 is less than, or almost equal to, val2. Fails +// otherwise. In particular, it fails if either val1 or val2 is NaN. +GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2, + float val1, float val2); +GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2, + double val1, double val2); + + +#if GTEST_OS_WINDOWS + +// Macros that test for HRESULT failure and success, these are only useful +// on Windows, and rely on Windows SDK macros and APIs to compile. +// +// * {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}(expr) +// +// When expr unexpectedly fails or succeeds, Google Test prints the +// expected result and the actual result with both a human-readable +// string representation of the error, if available, as well as the +// hex result code. +# define EXPECT_HRESULT_SUCCEEDED(expr) \ + EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr)) + +# define ASSERT_HRESULT_SUCCEEDED(expr) \ + ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr)) + +# define EXPECT_HRESULT_FAILED(expr) \ + EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr)) + +# define ASSERT_HRESULT_FAILED(expr) \ + ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr)) + +#endif // GTEST_OS_WINDOWS + +// Macros that execute statement and check that it doesn't generate new fatal +// failures in the current thread. +// +// * {ASSERT|EXPECT}_NO_FATAL_FAILURE(statement); +// +// Examples: +// +// EXPECT_NO_FATAL_FAILURE(Process()); +// ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed"; +// +#define ASSERT_NO_FATAL_FAILURE(statement) \ + GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_) +#define EXPECT_NO_FATAL_FAILURE(statement) \ + GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_) + +// Causes a trace (including the source file path, the current line +// number, and the given message) to be included in every test failure +// message generated by code in the current scope. The effect is +// undone when the control leaves the current scope. +// +// The message argument can be anything streamable to std::ostream. +// +// In the implementation, we include the current line number as part +// of the dummy variable name, thus allowing multiple SCOPED_TRACE()s +// to appear in the same block - as long as they are on different +// lines. +#define SCOPED_TRACE(message) \ + ::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\ + __FILE__, __LINE__, ::testing::Message() << (message)) + +// Compile-time assertion for type equality. +// StaticAssertTypeEq() compiles iff type1 and type2 are +// the same type. The value it returns is not interesting. +// +// Instead of making StaticAssertTypeEq a class template, we make it a +// function template that invokes a helper class template. This +// prevents a user from misusing StaticAssertTypeEq by +// defining objects of that type. +// +// CAVEAT: +// +// When used inside a method of a class template, +// StaticAssertTypeEq() is effective ONLY IF the method is +// instantiated. For example, given: +// +// template class Foo { +// public: +// void Bar() { testing::StaticAssertTypeEq(); } +// }; +// +// the code: +// +// void Test1() { Foo foo; } +// +// will NOT generate a compiler error, as Foo::Bar() is never +// actually instantiated. Instead, you need: +// +// void Test2() { Foo foo; foo.Bar(); } +// +// to cause a compiler error. +template +bool StaticAssertTypeEq() { + (void)internal::StaticAssertTypeEqHelper(); + return true; +} + +// Defines a test. +// +// The first parameter is the name of the test case, and the second +// parameter is the name of the test within the test case. +// +// The convention is to end the test case name with "Test". For +// example, a test case for the Foo class can be named FooTest. +// +// The user should put his test code between braces after using this +// macro. Example: +// +// TEST(FooTest, InitializesCorrectly) { +// Foo foo; +// EXPECT_TRUE(foo.StatusIsOK()); +// } + +// Note that we call GetTestTypeId() instead of GetTypeId< +// ::testing::Test>() here to get the type ID of testing::Test. This +// is to work around a suspected linker bug when using Google Test as +// a framework on Mac OS X. The bug causes GetTypeId< +// ::testing::Test>() to return different values depending on whether +// the call is from the Google Test framework itself or from user test +// code. GetTestTypeId() is guaranteed to always return the same +// value, as it always calls GetTypeId<>() from the Google Test +// framework. +#define GTEST_TEST(test_case_name, test_name)\ + GTEST_TEST_(test_case_name, test_name, \ + ::testing::Test, ::testing::internal::GetTestTypeId()) + +// Define this macro to 1 to omit the definition of TEST(), which +// is a generic name and clashes with some other libraries. +#if !GTEST_DONT_DEFINE_TEST +# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name) +#endif + +// Defines a test that uses a test fixture. +// +// The first parameter is the name of the test fixture class, which +// also doubles as the test case name. The second parameter is the +// name of the test within the test case. +// +// A test fixture class must be declared earlier. The user should put +// his test code between braces after using this macro. Example: +// +// class FooTest : public testing::Test { +// protected: +// virtual void SetUp() { b_.AddElement(3); } +// +// Foo a_; +// Foo b_; +// }; +// +// TEST_F(FooTest, InitializesCorrectly) { +// EXPECT_TRUE(a_.StatusIsOK()); +// } +// +// TEST_F(FooTest, ReturnsElementCountCorrectly) { +// EXPECT_EQ(0, a_.size()); +// EXPECT_EQ(1, b_.size()); +// } + +#define TEST_F(test_fixture, test_name)\ + GTEST_TEST_(test_fixture, test_name, test_fixture, \ + ::testing::internal::GetTypeId()) + +} // namespace testing + +// Use this function in main() to run all tests. It returns 0 if all +// tests are successful, or 1 otherwise. +// +// RUN_ALL_TESTS() should be invoked after the command line has been +// parsed by InitGoogleTest(). +// +// This function was formerly a macro; thus, it is in the global +// namespace and has an all-caps name. +int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_; + +inline int RUN_ALL_TESTS() { + return ::testing::UnitTest::GetInstance()->Run(); +} + +#endif // GTEST_INCLUDE_GTEST_GTEST_H_ diff --git a/ZaharovaDD/lab2/include/list.h b/ZaharovaDD/lab2/include/list.h new file mode 100644 index 000000000..fe5a668ba --- /dev/null +++ b/ZaharovaDD/lab2/include/list.h @@ -0,0 +1,170 @@ +#pragma once +#include "node.h" +#include + +using namespace std; + +//Шаблон клаÑÑа ЦикличеÑкий ÑпиÑок Ñ Ð³Ð¾Ð»Ð¾Ð²Ð¾Ð¹ +template +class list +{ +private: + node* head; //голова + node* Curr; //Указатель на текущий +public: + list(); //К. по умолчанию + ~list(); //ДеÑÑ‚руктор + list(const list& a); //К. + void Clean(); //очиÑтка ÑпиÑка + + void InsertInOrder(const TP& a); //Ð’Ñтавить в упорÑдоченный ÑпиÑок + void InsertAfter(node* a1, const TP& a2); //вÑтавить поÑле + void InsertToTail(const TP a); //вÑтавить в конец + + bool IsEmpty() const { return (head->next == head); }; //проверка на пуÑтоту + //напиÑать метод isfull + TP& GetCurr() const { return Curr->data; } //Получение текущего адреÑа + void Reset() { Curr = head->next; } //УÑтановка на начало + void gonext() { Curr = Curr->next; }; //переход на Ñледующее звено + bool IsOver() { if (Curr->next == head->next) return true; else return false; } //проверка на конец + + const list& operator=(const list& a); //Перегрузка оператора = + + bool operator==(const list& a) const; //Оператор ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ == + bool operator!=(const list& a) const { return !(*this == a); } //Оператор ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ Ð½Ðµ равно +}; + + +template //К. по умолчанию +list::list() +{ + head = new node(); + Curr = head->next; + head->next = head; +} + +template +list::~list() +{ + Clean(); + delete head; +} + + +template //К. ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ +list::list(const list& a) +{ + head = new node; + node* E1 = a.head; + node* E2 = head; + if (E1->next == a.head) + { + head->next = head; + return; + } + while (E1->next != a.head) + { + E1 = E1->next; + E2->next = new node(E1->data); + E2 = E2->next; + } + E2->next = head; + Curr = head->next; +} + +template //ОчиÑтка ÑпиÑка +void list::Clean() +{ + node* curr = head->next; + while (curr != head) + { + node* temp = curr->next; + delete curr; + curr = temp; + } + head->next = head; +} + + +template //Ð’Ñтавить в упорÑдоченный ÑпиÑок +void list::InsertInOrder(const TP& a) +{ + if (IsEmpty()) + { + head->next = new node(a); + head->next->next = head; + } + else + { + node* t = new node(a); + node* c = head; + + while (c->next != head && (*(c->next) < *t)) + { + c = c->next; + } + node* t1 = c->next; + c->next = t; + c->next->next = t1; + } +} + +template //вÑтавить поÑле +void list::InsertAfter(node* a1, const TP& a2) +{ + if (head == NULL) + throw "empty list"; + else + { + node* t = a1->next; + a1->next = new node(a2, t); + } +} + +template //вÑтавить в конец +void list ::InsertToTail(const TP a) +{ + Reset(); + while (Curr->next != head) + gonext(); + node* t = Curr->next; + Curr->next = new node(a); + Curr->next->next = t; +} + +template //приÑваивание +const list& list::operator=(const list& a) +{ + Clean(); + node* p_a = a.head; + node* p_curr = head; + while (p_a->next != a.head) + { + p_a = p_a->next; + p_curr->next = new node(p_a->data); + p_curr = p_curr->next; + } + p_curr->next = head; + Curr = head->next; + return *this; +} + + +template //Ñравнение +bool list::operator==(const list& a) const +{ + bool res = true; + if (this != &a) + { + node* t1 = a.head->next; + node* t2 = head->next; + while (t1->data == t2->data && t2 != head && t1 != a.head) + { + t1 = t1->next; + t2 = t2->next; + } + if (t2 != head || t1 != a.head) + res = false; + } + return res; +} diff --git a/ZaharovaDD/lab2/include/monom.h b/ZaharovaDD/lab2/include/monom.h new file mode 100644 index 000000000..40b26b11f --- /dev/null +++ b/ZaharovaDD/lab2/include/monom.h @@ -0,0 +1,20 @@ +#pragma once +#include + + +class monom +{ +public: + double cff; //Êîýôô. ïåðåä ìîíîìîì + int svr; //Ñâ¸ðíóòàÿ ñòåïåíü + + monom(const monom& a) { cff = a.cff; svr = a.svr; } + monom(const double index_cff = 0.0, const unsigned int index_svr = 0) { cff = index_cff; svr = index_svr; } //Ê. + const monom& operator=(const monom& a) { cff = a.cff; svr = a.svr; return *this; } //Î. ïðèñâàèâàíèÿ + bool operator< (const monom& a) const { return (svr (const monom& a) const { return (svr>a.svr); } //Î. ñðàâíåíèÿ + bool operator==(const monom& a) const { return ((svr == a.svr) && (cff == a.cff)); } //ïåðåãðóæåíî == + bool operator!=(const monom& a) const { return !(*this == a); } //ïåðåãðóæåíî != + + +}; diff --git a/ZaharovaDD/lab2/include/node.h b/ZaharovaDD/lab2/include/node.h new file mode 100644 index 000000000..66f51b1c9 --- /dev/null +++ b/ZaharovaDD/lab2/include/node.h @@ -0,0 +1,16 @@ +#pragma once + +//Шаблон клаÑÑа "Элемент ÑпиÑка" +template +class node +{ +public: + TP data; //Данные в Ñл. + node* next; //Указатель на Ñледующий Ñл. + + node() { next = NULL; }; //К. по умолчанию + node(TP a1, node* a2 = NULL) { data = a1; next = a2; }; //К. Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð¾Ð¼ + bool operator< (const node& a) const { return (data < a.data); }; //О. ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ + bool operator> (const node& a) const { return (data > a.data); }; //О. ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ +}; + diff --git a/ZaharovaDD/lab2/include/polynom.h b/ZaharovaDD/lab2/include/polynom.h new file mode 100644 index 000000000..48e9ff458 --- /dev/null +++ b/ZaharovaDD/lab2/include/polynom.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include +#include "monom.h" +#include "list.h" + +#define OFFSET 120 //Код Ñимвола 'x' + +class polynom +{ +private: + list list_monom; //ÑпиÑок мономов + list such(list & op); //объединение подобные + +public: + polynom(const polynom& p); + const polynom& operator=(const polynom &p); + polynom(list &in_list) : list_monom(in_list) {} //К. по ÑпиÑку + polynom(const string op = ""); //К. по Ñтроке + + polynom operator-(const polynom& p) const { return *this + p*(-1); } //Бинарный Ð¼Ð¸Ð½ÑƒÑ + polynom operator-() const { return (-1)*(*this); } //Унарный Ð¼Ð¸Ð½ÑƒÑ + bool operator==(const polynom& p) const { return list_monom == p.list_monom; } //О. ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ + bool operator!=(const polynom& p) const { return list_monom != p.list_monom; } //О. ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ + polynom operator+(const polynom& p) const; //О. ÑÐ»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»Ð¸Ð½Ð¾Ð¼Ð¾Ð² + polynom operator*(const polynom& p) const; //О. ÑƒÐ¼Ð½Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»Ð¸Ð½Ð¾Ð¼Ð¾Ð² + polynom operator*(const double k) const; //Умножение на конÑтанту + friend polynom operator*(const double k, const polynom& p) { return p*k; } //Умножение на конÑтанту Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð¹ Ñтороны + + friend std::ostream& operator<<(std::ostream &str, const polynom &p); //О. вÑтавки в поток +}; \ No newline at end of file diff --git a/ZaharovaDD/lab2/include/table.h b/ZaharovaDD/lab2/include/table.h new file mode 100644 index 000000000..ec43b1bfd --- /dev/null +++ b/ZaharovaDD/lab2/include/table.h @@ -0,0 +1,64 @@ +#pragma once +#define MIN_DIM 50 +#include +#include +template +struct RecordTable //Äàííûå, êîòîðûå õðàíèò òàáëèöà +{ + key_T key; //Êëþ÷ + data_T data; //Äàííûå,êîòîðûå õðàíÿòñÿ â òàáëèöå-óêàçàòåëü + + RecordTable(key_T _k = key_T(), data_T _d = data_T()) { key = _k; data = _d; } //ê. +}; + +template +class Table //Êëàññ òàáëèö (àáñòðàêòíûé) +{ + +protected: + RecordTable ** A_T; //Ìàññèâ óêàçàòåëåé íà çàïèñè + int Max_Dim; //Ðàçìåð òàáëèöû + int Index; //Âåðõíèé ýëåìåíò + int _Dim; //Èíäåêñ ôàêòè÷åñêîé çàïèñè + virtual void Repack() = 0; //Ôóíêöèÿ, óâåëè÷èâàþùàÿ ðàçìåð òàáëèöû + +public: + Table(int Dim_Tb = MIN_DIM); //Ê. + virtual ~Table() { for (int i = 0; i < Max_Dim; i++) delete A_T[i]; delete[] A_T; };//äåñòðóêòîð + virtual void Insert(const key_T &_k, const data_T &_d) = 0; + virtual void Dell(const key_T &_k) = 0; + virtual RecordTable * Search(const key_T &_k) const = 0; //Óêàçàòåëü + + //Ìåòîäû íàâèãàöèè + void Reset() { _Dim = 0; }; //Òåêóùèé ýëåìåíò = 0 + //virtual void Move() { _Dim++; if (Index == _Dim) Reset(); }; + bool IsTableEnd() const { if (Index == 0) return true; if (_Dim == Index - 1) return 1; else return 0; }; //Ïðîâåðÿåì íà êîíåö + void GoNext() { if (!IsTableEnd())_Dim++; }; //Óñòàíîâêà ñëåäóþùåãî èíäåêñà + data_T GetCurr() const { return (*(this->A_T[_Dim])).data; }; //Ïðîñìîòð òåêóùåãî ýëåìåíòà + template friend std::ostream& operator<<(std::ostream& os, const Table& P); //Âñòàâêà â ïîòîê + +}; + + +template +Table::Table(int Dim_Tb) +{ + Max_Dim = Dim_Tb; + A_T = new RecordTable *[Dim_Tb]; + for (int i = 0; i < Dim_Tb; i++) + A_T[i] = NULL; + Index = 0; + _Dim = 0; +}; + +template +std::ostream& operator << (std::ostream& os, const Table& P) +{ + for (int i = 0; i " << " " << (*(P.A_T[i])).data << endl; + else os << i << ": " << " NULL" << endl; + } + return os; +} \ No newline at end of file diff --git a/ZaharovaDD/lab2/include/tableHash.h b/ZaharovaDD/lab2/include/tableHash.h new file mode 100644 index 000000000..55e4d3879 --- /dev/null +++ b/ZaharovaDD/lab2/include/tableHash.h @@ -0,0 +1,155 @@ +#pragma once +#include "table.h" +#include +using namespace std; +//0 - ñâîáîäåí; +//1 - ìåñòî çàíÿòî; +//-1 - áûë óäàë¸í; + +template +class TableHash : public Table +{ +public: + TableHash(int Dim = 20) : Table(Dim) { P_ = new int[Dim]; for (int i = 0; i < Dim; i++) P_[i] = 0; }; //Ê. + ~TableHash() {}; + void Insert(const key_T &_k, const data_T &_d); //Âñòàâêà + void Dell(const key_T &_k); //Óäàëåíèå ýëåìåíòà + RecordTable* Search(const key_T &_k) const; //Ïîèñê ýëåìåíòà ïî êëþ÷ó +private: + int *P_; + + void Repack(); //Ïåðåõåøèðîâàíèå + int Hash_function(const key_T &k) const; +}; + +template +int Get_Key(const key_T& k) { return 0; } + +template<> +int Get_Key(const string &k) //Õýø - ôóíêöèè (îò string) +{ + int g = 31; + int hash = 0; + for (int i = 0; i < k.length(); i++) + hash = g * hash + k[i]; + return hash; +} + +template //Õýø-ôóíêöèÿ ÌÅÒÎÄ +int TableHash::Hash_function(const key_T& k) const +{ + int temp = abs(Get_Key(k)); + return (temp % (this->Max_Dim)); +} + +template +void TableHash::Repack() +{ + int i = 0; + int Nxt_Dim = (int)(this->Max_Dim + 20)*1.5; + RecordTable ** New_A = new RecordTable *[Nxt_Dim]; + int * PM_ = new int[Nxt_Dim]; + for (int i = 0; i < this->Max_Dim; i++) + PM_[i] = P_[i]; + for (int i = this->Max_Dim; i < Nxt_Dim; i++) + PM_[i] = 0; + delete[]P_; + P_ = PM_; + for (int i = 0; iMax_Dim; i++) + New_A[i] = this->A_T[i]; + for (int i = this->Max_Dim; i < Nxt_Dim; i++) + New_A[i] = NULL; + delete[] this->A_T; + this->A_T = New_A; + this->Max_Dim = Nxt_Dim; +} + +template +void TableHash::Insert(const key_T &_k, const data_T &_d) +{ + if ((double)this->_Dim / (double)this->Max_Dim > 0.7) // ïåðåðàñïðåäåëèòü åñëè äî çàïîëíåíèÿ îñòàëîñü 40 ïðîöåíòîâ + Repack(); + int loc = Hash_function(_k); + if (P_[loc] == 0) //ÿ÷åéêà ñâîáîäíà + { + this->A_T[loc] = new RecordTable(_k, _d); + P_[loc] = 1; + this->_Dim++; + } + else if (P_[loc] == -1) + { + this->A_T[loc] = new RecordTable(_k, _d); + P_[loc] = 1; + } + else + { + if ((*(this->A_T[loc])).key == _k) + { + throw "key - duplicated"; + } + int label = loc + 1; + while (P_[label] == 1) //ïîêà ýëåìåíò çàíÿò + { + label = label + 1; + if ((this->A_T[label] != NULL) && ((*(this->A_T[label])).key == _k)) + { + throw "key - duplicated"; + } + } + this->A_T[label] = new RecordTable(_k, _d); + if (P_[label] == 0) + this->_Dim++; + P_[label] = 1; + } +} + +template +void TableHash::Dell(const key_T &_k) +{ + int loc = Hash_function(_k); + if (P_[loc] == 0) //ýëåìåíòà íåò + throw "item does not exist"; + if ((this->A_T[loc] != NULL) && ((*(this->A_T[loc])).key == _k)) + { + delete this->A_T[loc]; + this->A_T[loc] = NULL; + P_[loc] = -1; + } + else + { + while ((P_[loc] == -1) || ((P_[loc] == 1) && ((*(this->A_T[loc])).key != _k))) //åñëè ýëåìåíò áûë óäàë¸í, èëè îí çàíÿò, íî íå ñîâïàäàþò êëþ÷è - îáíîâèòü ìåñòî + loc = loc + 1; + if (P_[loc] == 1) // ñîâïàäàþò êëþ÷è + { + delete this->A_T[loc]; + this->A_T[loc] = NULL; + P_[loc] = -1; + } + else throw "item does not exist"; + } +} + + +template +RecordTable* TableHash::Search(const key_T &_k) const +{ + int loc = Hash_function(_k); + if (P_[loc] == 0) //ýëåìåíòà íåò + throw "item does not exist"; + if ((this->A_T[loc] != NULL) && ((*(this->A_T[loc])).key) == _k) + { + return this->A_T[loc]; + } + else + { + while ((P_[loc] == -1) || ((P_[loc] == 1) && ((*(this->A_T[loc])).key != _k))) //åñëè ýëåìåíò áûë óäàë¸í, èëè îí çàíÿò, íî íå ñîâïàäàþò êëþ÷è - îáíîâèòü ìåñòî + loc = loc + 1; + if (P_[loc] == 1) // ñîâïàäàþò êëþ÷è + { + return this->A_T[loc]; + } + else + throw "item does not exist"; + } + +} diff --git a/ZaharovaDD/lab2/include/tableOrder.h b/ZaharovaDD/lab2/include/tableOrder.h new file mode 100644 index 000000000..594b829d2 --- /dev/null +++ b/ZaharovaDD/lab2/include/tableOrder.h @@ -0,0 +1,94 @@ + +#pragma once +#include "table.h" + +template +class TableOrder : public Table +{ +public: + TableOrder(int Dim = MIN_DIM) : Table(Dim) {}; + virtual ~TableOrder() {}; + virtual void Insert(const key_T &_k, const data_T &_d); //Âñòàâêà + virtual void Dell(const key_T &_k); //Óäàëåíèå + virtual RecordTable* Search(const key_T &_k) const; //Ïîèñê (ïî êëþ÷ó) +private: + virtual void Repack(); //Ôóíêöèÿ, óâåëè÷èâàþùàÿ ðàçìåð òàáëèöû + int BinarSearch(const key_T &Key) const; //Áèíàðíûé ïîèñê +}; + +template +void TableOrder ::Insert(const key_T &_k, const data_T &_d) +{ + int pa = BinarSearch(_k); + int i; + if ((this->A_T[pa] == NULL) || ((*(this->A_T[pa])).key != _k)) + { + if ((double)this->Index / (double)this->Max_Dim > 0.7) // ïåðåðàñïðåäåëèòü åñëè äî çàïîëíåíèÿ îñòàëîñü 30 ïðîöåíòîâ + Repack(); + for (i = this->Index; i > pa; i--) + this->A_T[i] = this->A_T[i - 1]; + this->A_T[i] = new RecordTable(_k, _d); + this->Index++; + } + else throw "key - duplicate"; +} + +template +void TableOrder ::Dell(const key_T &_k) +{ + int pa = BinarSearch(_k); + + if ((this->A_T[pa] != NULL) && ((*(this->A_T[pa])).key == _k)) + { + delete this->A_T[pa]; + for (int i = pa; i < this->Index; i++) + this->A_T[i] = this->A_T[i + 1]; + this->Index -= 1; + } + else + throw "item does not exist"; +} + +template +RecordTable* TableOrder ::Search(const key_T &_k) const +{ + int pa = BinarSearch(_k); + if ((this->A_T[pa]!=NULL)&&((*(this->A_T[pa])).key == _k)) + return this->A_T[pa]; + else + throw "item does not exist"; +} + +template +void TableOrder ::Repack() +{ + int Nxt_Dim = (int)(this->Max_Dim + 20)*1.65; + RecordTable ** New_A = new RecordTable *[Nxt_Dim]; + for (int i = 0; iMax_Dim; i++) + New_A[i] = this->A_T[i]; + for (int i = this->Max_Dim; iA_T; + this->A_T = New_A; + this->Max_Dim = Nxt_Dim; +} + +template +int TableOrder ::BinarSearch(const key_T &k) const //âîçâðàùàåò èíäåêñ (íîìåð ñòðîêè â òàáëèöå) +{ + int right = this->Index - 1; + int mid = 0; + int left = 0; + while (right >= left) + { + mid = (right + left) / 2; + if ((*(this->A_T[mid])).key < k) + left = mid + 1; + else if ((*(this->A_T[mid])).key > k) + right = mid - 1; + else return mid; + } + if (left > right) + mid = left; + return mid; +} diff --git a/ZaharovaDD/lab2/include/tableUnorder.h b/ZaharovaDD/lab2/include/tableUnorder.h new file mode 100644 index 000000000..32d970c98 --- /dev/null +++ b/ZaharovaDD/lab2/include/tableUnorder.h @@ -0,0 +1,82 @@ +#pragma once +#include "table.h" +#include "math.h" +#include +using namespace std; +template +class TableUnorder : public Table +{ +public: + TableUnorder(int Dim = MIN_DIM) : Table(Dim) {}; //Ê. + virtual ~TableUnorder() {}; //Äåñòðóêòîð + virtual void Insert(const key_T &_k, const data_T &_d); //Âñòàâêà + virtual void Dell(const key_T &_k); //Óäàëåíèå ýëåìåíòà + virtual RecordTable* Search(const key_T &_k) const; //Ïîèñê ýëåìåíòà (ïî êëþ÷ó) + +private: + virtual void Repack(); //Ôóíêöèÿ, óâåëè÷èâàþùàÿ ðàçìåð òàáëèöû +}; + +template +void TableUnorder< key_T, data_T> ::Insert(const key_T &_k, const data_T &_d) +{ + if ((double)this->Index / (double)this->Max_Dim > 0.7) // ïåðåðàñïðåäåëèòü åñëè äî çàïîëíåíèÿ îñòàëîñü ìåíåå 30 ïðîöåíòîâ + Repack(); + for (int i = 0; i < this->Index; i++) + { + if ((*(this->A_T[i])).key == _k) + { + throw "key - duplicate"; //êëþ÷ äóáëèðóåòñÿ + } + } + this->A_T[this->Index++] = new RecordTable(_k, _d); +}; + +template +void TableUnorder< key_T, data_T> ::Dell(const key_T &_k) +{ + int i = 0; + int FLAG = 0; + while ((i < this->Index) && (FLAG == 0)) { + if ((*(this->A_T[i])).key == _k) FLAG = 1; + i++; + } + if (FLAG == 1) { + i--; + delete this->A_T[i]; + while (i < this->Index - 1) { + this->A_T[i] = this->A_T[i + 1]; + i++; + } + this->A_T[i] = NULL; + this->Index--; + } + else throw "item does not exist"; //ýëåìåíò íå ñóùåñòâóåò +}; + +template +RecordTable* TableUnorder< key_T, data_T> ::Search(const key_T &_k) const +{ + int i = 0; + while (i < this->Index) + { + if ((*(this->A_T[i])).key == _k) + return this->A_T[i]; + i++; + } + throw "item does not exist"; +} + +template +void TableUnorder ::Repack() +{ + int Nxt_Dim = (int)(this->Max_Dim + 20)*1.65; + RecordTable ** New_A = new RecordTable*[Nxt_Dim]; + for (int i = 0; iMax_Dim; i++) + New_A[i] = this->A_T[i]; + for (int i = this->Max_Dim; iA_T; + this->A_T = New_A; + this->Max_Dim = Nxt_Dim; +}; diff --git a/ZaharovaDD/lab2/otchet_table.docx b/ZaharovaDD/lab2/otchet_table.docx new file mode 100644 index 0000000000000000000000000000000000000000..1d1dd694171d124fc917c53077437575011b9d34 GIT binary patch literal 124816 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≤t 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 literal 0 HcmV?d00001 diff --git a/ZaharovaDD/lab2/samples/main_table.cpp b/ZaharovaDD/lab2/samples/main_table.cpp new file mode 100644 index 000000000..6e3ccb959 --- /dev/null +++ b/ZaharovaDD/lab2/samples/main_table.cpp @@ -0,0 +1,109 @@ +#include "monom.h" +#include "polynom.h" +#include +#include +#include "tableUnorder.h" +#include "tableOrder.h" +#include "tableHash.h" +using namespace std; + +int main() +{ + int c = 0; + int k; + int SIZE; + + cout << "Enter the size of the table" << endl; + cin >> SIZE; + TableUnorder A(SIZE); + string a; + TableOrder B(SIZE); + TableHash C(SIZE); + + while (c != 1) + { + system("cls"); + cout << "Chouse operation" << endl; + cout << "1 - Insert" << endl; + cout << "2 - Dell" << endl; + cout << "3 - Search" << endl; + cout << "4 - Print" << endl; + cin >> k; + switch (k) + { + case 1: + { + string str; + cout << "Write your Polinom" << endl; + cin >> str; + polynom a(str); + try { A.Insert(str, a); } + catch (...) { cout << "duplicated key" << endl; } + try { B.Insert(str, a); } + catch (...) { cout << "duplicated key" << endl; } + try { C.Insert(str, a); } + catch (...) { cout << "duplicated key" << endl; } + cout << "Unordered :" << endl; + cout << A << endl; + cout << "Ordered :" << endl; + cout << B << endl; + cout << "Hash :" << endl; + cout << C << endl; + break; + } + case 2: + { + string str; + cout << "Write polynom" << endl; + cin >> str; + polynom a(str); + try { A.Dell(str); } + catch (...) { cout << "element doesn't exist" << endl; } + try { B.Dell(str); } + catch (...) { cout << "element doesn't exist" << endl; } + try { C.Dell(str); } + catch (...) { cout << "element doesn't exist" << endl; } + cout << "Unordered :" << endl; + cout << A << endl; + cout << "Ordered :" << endl; + cout << B << endl; + cout << "Hash :" << endl; + cout << C << endl; + break; + } + case 3: + { + string str; + cout << "Write polynom" << endl; + cin >> str; + polynom a(str); + try { cout << "finded: " << A.Search(str)->data; } + catch (...) { cout << "element doesn't exist" << endl; } + try { cout << "finded: " << B.Search(str)->data; } + catch (...) { cout << "element doesn't exist" << endl; } + try { cout << "finded: " << C.Search(str)->data; } + catch (...) { cout << "element doesn't exist" << endl; } + break; + } + case 4: + { + cout << "Unordered :" << endl; + cout << A << endl; + cout << "Ordered :" << endl; + cout << B << endl; + cout << "Hash :" << endl; + cout << C << endl; + break; + } + default: + { + cout << "ERROR, choose again" << endl; + break; + } + } + + cout << "Exit - 1" << endl; + cin >> c; + } + return 0; +} \ No newline at end of file diff --git a/ZaharovaDD/lab2/sln/table/gtest/gtest.vcxproj b/ZaharovaDD/lab2/sln/table/gtest/gtest.vcxproj new file mode 100644 index 000000000..9d19d7b1f --- /dev/null +++ b/ZaharovaDD/lab2/sln/table/gtest/gtest.vcxproj @@ -0,0 +1,138 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + {5CF9CCD7-9FAE-46C3-B8AB-F3A13AED5595} + Win32Proj + gtest + 8.1 + + + + StaticLibrary + true + v140 + Unicode + + + StaticLibrary + false + v140 + true + Unicode + + + StaticLibrary + true + v140 + Unicode + + + StaticLibrary + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/ZaharovaDD/lab2/sln/table/gtest/gtest.vcxproj.filters b/ZaharovaDD/lab2/sln/table/gtest/gtest.vcxproj.filters new file mode 100644 index 000000000..39debc049 --- /dev/null +++ b/ZaharovaDD/lab2/sln/table/gtest/gtest.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + + + Заголовочные файлы + + + + + Файлы иÑходного кода + + + \ No newline at end of file diff --git a/ZaharovaDD/lab2/sln/table/samples/samples.vcxproj b/ZaharovaDD/lab2/sln/table/samples/samples.vcxproj new file mode 100644 index 000000000..651ff2d92 --- /dev/null +++ b/ZaharovaDD/lab2/sln/table/samples/samples.vcxproj @@ -0,0 +1,162 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {F01305A0-4E40-4C76-8EB4-3CE5CBB146C4} + Win32Proj + samples + 8.1 + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\include + + + Console + true + ..\Debug + table.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\include + + + Console + true + ..\Debug + table.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\include + + + Console + true + true + true + ..\Release + table.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\include + + + Console + true + true + true + ..\Release + table.lib;%(AdditionalDependencies) + + + + + + + + + \ No newline at end of file diff --git a/ZaharovaDD/lab2/sln/table/samples/samples.vcxproj.filters b/ZaharovaDD/lab2/sln/table/samples/samples.vcxproj.filters new file mode 100644 index 000000000..e2af6dace --- /dev/null +++ b/ZaharovaDD/lab2/sln/table/samples/samples.vcxproj.filters @@ -0,0 +1,14 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Файлы иÑходного кода + + + \ No newline at end of file diff --git a/ZaharovaDD/lab2/sln/table/table.sln b/ZaharovaDD/lab2/sln/table/table.sln new file mode 100644 index 000000000..ccd045fd0 --- /dev/null +++ b/ZaharovaDD/lab2/sln/table/table.sln @@ -0,0 +1,65 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest", "gtest\gtest.vcxproj", "{5CF9CCD7-9FAE-46C3-B8AB-F3A13AED5595}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "table", "table\table.vcxproj", "{E8F74751-D5E2-4E22-8331-7A065D0B2824}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "samples", "samples\samples.vcxproj", "{F01305A0-4E40-4C76-8EB4-3CE5CBB146C4}" + ProjectSection(ProjectDependencies) = postProject + {E8F74751-D5E2-4E22-8331-7A065D0B2824} = {E8F74751-D5E2-4E22-8331-7A065D0B2824} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcxproj", "{182B1D93-7A68-497D-B0EA-222153670B06}" + ProjectSection(ProjectDependencies) = postProject + {E8F74751-D5E2-4E22-8331-7A065D0B2824} = {E8F74751-D5E2-4E22-8331-7A065D0B2824} + {5CF9CCD7-9FAE-46C3-B8AB-F3A13AED5595} = {5CF9CCD7-9FAE-46C3-B8AB-F3A13AED5595} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5CF9CCD7-9FAE-46C3-B8AB-F3A13AED5595}.Debug|x64.ActiveCfg = Debug|x64 + {5CF9CCD7-9FAE-46C3-B8AB-F3A13AED5595}.Debug|x64.Build.0 = Debug|x64 + {5CF9CCD7-9FAE-46C3-B8AB-F3A13AED5595}.Debug|x86.ActiveCfg = Debug|Win32 + {5CF9CCD7-9FAE-46C3-B8AB-F3A13AED5595}.Debug|x86.Build.0 = Debug|Win32 + {5CF9CCD7-9FAE-46C3-B8AB-F3A13AED5595}.Release|x64.ActiveCfg = Release|x64 + {5CF9CCD7-9FAE-46C3-B8AB-F3A13AED5595}.Release|x64.Build.0 = Release|x64 + {5CF9CCD7-9FAE-46C3-B8AB-F3A13AED5595}.Release|x86.ActiveCfg = Release|Win32 + {5CF9CCD7-9FAE-46C3-B8AB-F3A13AED5595}.Release|x86.Build.0 = Release|Win32 + {E8F74751-D5E2-4E22-8331-7A065D0B2824}.Debug|x64.ActiveCfg = Debug|x64 + {E8F74751-D5E2-4E22-8331-7A065D0B2824}.Debug|x64.Build.0 = Debug|x64 + {E8F74751-D5E2-4E22-8331-7A065D0B2824}.Debug|x86.ActiveCfg = Debug|Win32 + {E8F74751-D5E2-4E22-8331-7A065D0B2824}.Debug|x86.Build.0 = Debug|Win32 + {E8F74751-D5E2-4E22-8331-7A065D0B2824}.Release|x64.ActiveCfg = Release|x64 + {E8F74751-D5E2-4E22-8331-7A065D0B2824}.Release|x64.Build.0 = Release|x64 + {E8F74751-D5E2-4E22-8331-7A065D0B2824}.Release|x86.ActiveCfg = Release|Win32 + {E8F74751-D5E2-4E22-8331-7A065D0B2824}.Release|x86.Build.0 = Release|Win32 + {F01305A0-4E40-4C76-8EB4-3CE5CBB146C4}.Debug|x64.ActiveCfg = Debug|x64 + {F01305A0-4E40-4C76-8EB4-3CE5CBB146C4}.Debug|x64.Build.0 = Debug|x64 + {F01305A0-4E40-4C76-8EB4-3CE5CBB146C4}.Debug|x86.ActiveCfg = Debug|Win32 + {F01305A0-4E40-4C76-8EB4-3CE5CBB146C4}.Debug|x86.Build.0 = Debug|Win32 + {F01305A0-4E40-4C76-8EB4-3CE5CBB146C4}.Release|x64.ActiveCfg = Release|x64 + {F01305A0-4E40-4C76-8EB4-3CE5CBB146C4}.Release|x64.Build.0 = Release|x64 + {F01305A0-4E40-4C76-8EB4-3CE5CBB146C4}.Release|x86.ActiveCfg = Release|Win32 + {F01305A0-4E40-4C76-8EB4-3CE5CBB146C4}.Release|x86.Build.0 = Release|Win32 + {182B1D93-7A68-497D-B0EA-222153670B06}.Debug|x64.ActiveCfg = Debug|x64 + {182B1D93-7A68-497D-B0EA-222153670B06}.Debug|x64.Build.0 = Debug|x64 + {182B1D93-7A68-497D-B0EA-222153670B06}.Debug|x86.ActiveCfg = Debug|Win32 + {182B1D93-7A68-497D-B0EA-222153670B06}.Debug|x86.Build.0 = Debug|Win32 + {182B1D93-7A68-497D-B0EA-222153670B06}.Release|x64.ActiveCfg = Release|x64 + {182B1D93-7A68-497D-B0EA-222153670B06}.Release|x64.Build.0 = Release|x64 + {182B1D93-7A68-497D-B0EA-222153670B06}.Release|x86.ActiveCfg = Release|Win32 + {182B1D93-7A68-497D-B0EA-222153670B06}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ZaharovaDD/lab2/sln/table/table/table.vcxproj b/ZaharovaDD/lab2/sln/table/table/table.vcxproj new file mode 100644 index 000000000..c7bb9ed37 --- /dev/null +++ b/ZaharovaDD/lab2/sln/table/table/table.vcxproj @@ -0,0 +1,192 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + ..\..\..\include + ..\..\..\include + ..\..\..\include + ..\..\..\include + + + ..\..\..\include + ..\..\..\include + ..\..\..\include + ..\..\..\include + + + ..\..\..\include + ..\..\..\include + ..\..\..\include + ..\..\..\include + + + ..\..\..\include + ..\..\..\include + ..\..\..\include + ..\..\..\include + + + ..\..\..\include + ..\..\..\include + ..\..\..\include + ..\..\..\include + + + ..\..\..\include + ..\..\..\include + ..\..\..\include + ..\..\..\include + + + ..\..\..\include + ..\..\..\include + ..\..\..\include + ..\..\..\include + + + ..\..\..\include + ..\..\..\include + ..\..\..\include + ..\..\..\include + + + + {E8F74751-D5E2-4E22-8331-7A065D0B2824} + Win32Proj + table + 8.1 + + + + StaticLibrary + true + v140 + Unicode + + + StaticLibrary + false + v140 + true + Unicode + + + StaticLibrary + true + v140 + Unicode + + + StaticLibrary + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + + + Level3 + Disabled + _DEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/ZaharovaDD/lab2/sln/table/table/table.vcxproj.filters b/ZaharovaDD/lab2/sln/table/table/table.vcxproj.filters new file mode 100644 index 000000000..e03afce18 --- /dev/null +++ b/ZaharovaDD/lab2/sln/table/table/table.vcxproj.filters @@ -0,0 +1,65 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + \ No newline at end of file diff --git a/ZaharovaDD/lab2/sln/table/test/test.vcxproj b/ZaharovaDD/lab2/sln/table/test/test.vcxproj new file mode 100644 index 000000000..028a2ec89 --- /dev/null +++ b/ZaharovaDD/lab2/sln/table/test/test.vcxproj @@ -0,0 +1,165 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {182B1D93-7A68-497D-B0EA-222153670B06} + Win32Proj + test + 8.1 + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\include; ..\..\..\gtest + + + Console + true + table.lib;gtest.lib;%(AdditionalDependencies) + ..\Debug + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\include; ..\..\..\gtest + + + Console + true + table.lib;gtest.lib;%(AdditionalDependencies) + ..\Debug + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\include; ..\..\..\gtest + + + Console + true + true + true + table.lib;gtest.lib;%(AdditionalDependencies) + ..\Release + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\..\include; ..\..\..\gtest + + + Console + true + true + true + table.lib;gtest.lib;%(AdditionalDependencies) + ..\Release + + + + + + + + + + + + \ No newline at end of file diff --git a/ZaharovaDD/lab2/sln/table/test/test.vcxproj.filters b/ZaharovaDD/lab2/sln/table/test/test.vcxproj.filters new file mode 100644 index 000000000..6c6b66dca --- /dev/null +++ b/ZaharovaDD/lab2/sln/table/test/test.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + Файлы иÑходного кода + + + \ No newline at end of file diff --git a/ZaharovaDD/lab2/src/list.cpp b/ZaharovaDD/lab2/src/list.cpp new file mode 100644 index 000000000..c1d8a57a9 --- /dev/null +++ b/ZaharovaDD/lab2/src/list.cpp @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/ZaharovaDD/lab2/src/monom.cpp b/ZaharovaDD/lab2/src/monom.cpp new file mode 100644 index 000000000..dbbf93531 --- /dev/null +++ b/ZaharovaDD/lab2/src/monom.cpp @@ -0,0 +1 @@ +#include "monom.h" \ No newline at end of file diff --git a/ZaharovaDD/lab2/src/node.cpp b/ZaharovaDD/lab2/src/node.cpp new file mode 100644 index 000000000..eed307217 --- /dev/null +++ b/ZaharovaDD/lab2/src/node.cpp @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/ZaharovaDD/lab2/src/polynom.cpp b/ZaharovaDD/lab2/src/polynom.cpp new file mode 100644 index 000000000..975297297 --- /dev/null +++ b/ZaharovaDD/lab2/src/polynom.cpp @@ -0,0 +1,231 @@ +#include "polynom.h" + +using namespace std; + +list polynom::such(list & op) +{ + list res; + res.Reset(); + op.Reset(); + node mon(op.GetCurr().cff); + list y(op); + while (!op.IsOver()) + { + mon.data.svr = op.GetCurr().svr; + y.gonext(); + if (op.GetCurr().svr == y.GetCurr().svr && (y.GetCurr().cff || y.GetCurr().svr)) + mon.data.cff += y.GetCurr().cff; + else + { + if (mon.data.cff) + { + res.InsertToTail(mon.data); + res.gonext(); + } + mon.data.cff = y.GetCurr().cff; + } + op.gonext(); + } + return res; +} + +polynom::polynom(const polynom& p) +{ + list_monom = p.list_monom; +} + +polynom::polynom(string op) +{ + int d[3] = { 100,10,1 }; + while (op.length()) + { + string pt; + monom t; + int pos = 1; + while (pos < op.length() && op[pos] != '+' && op[pos] != '-') + pos++; + pt = op.substr(0, pos); //áåðåò ñ íóëåâîé ïîçèöèè pos ýë-òîâ + op.erase(0, pos); //Óäàëÿåò ýëåìåíòû â äèàïàçîíå + pos = 0; + while (pt[pos] != 'x' && pt[pos] != 'y' && pt[pos] != 'z' && pos < pt.length()) + pos++; + + string pstr = pt.substr(0, pos); + if (pstr == "+" || pstr.length() == 0) + t.cff = 1; + else if (pstr == "-") + t.cff = -1; + else t.cff = stod(pstr); //ïðåîáðàçîâàíèå ñòðîêè â ÷èñëî + + pt.erase(0, pos); + pt += ' '; + + for (int i = 0; i < 3; i++) + { + pos = pt.find((char)(OFFSET + i)); + if (pos > -1) + { + if (pt[pos + 1] != '^') + pt.insert(pos + 1, "^1"); + t.svr += d[i] * stoi(pt.substr(pos + 2, 1)); // ïðåîáðàçóåò ïîñëåäîâàòåëüíîñòü ýëåìåíòîâ â öåëîå ÷èñëî. + pt.erase(pos, 3); + } + } + + list_monom.InsertInOrder(t); + } + + list_monom = such(list_monom); +} + + +const polynom & polynom::operator=(const polynom & p) +{ + list_monom = p.list_monom; + return *this; +} + +polynom polynom::operator+(const polynom& p) const +{ + + polynom res; + polynom pthis = *this; + polynom pol = p; + + pthis.list_monom.Reset(); + pol.list_monom.Reset(); + res.list_monom.Reset(); + + while (!pthis.list_monom.IsOver() && !pol.list_monom.IsOver()) + { + if (pthis.list_monom.GetCurr() > pol.list_monom.GetCurr()) //óïîðÿäî÷èâàíèå + { + res.list_monom.InsertToTail(pol.list_monom.GetCurr()); + pol.list_monom.gonext(); + res.list_monom.gonext(); + } + else if (pthis.list_monom.GetCurr() < pol.list_monom.GetCurr()) + { + res.list_monom.InsertToTail(pthis.list_monom.GetCurr()); + pthis.list_monom.gonext(); + res.list_monom.gonext(); + } + else + { + double new_c = pthis.list_monom.GetCurr().cff + pol.list_monom.GetCurr().cff; + if (new_c) + { + res.list_monom.InsertToTail(monom(new_c, pthis.list_monom.GetCurr().svr)); + res.list_monom.gonext(); + } + pthis.list_monom.gonext(); + pol.list_monom.gonext(); + } + } + while (!pthis.list_monom.IsOver()) + { + res.list_monom.InsertToTail(pthis.list_monom.GetCurr()); + pthis.list_monom.gonext(); + res.list_monom.gonext(); + } + while (!pol.list_monom.IsOver()) + { + res.list_monom.InsertToTail(pol.list_monom.GetCurr()); + pol.list_monom.gonext(); + res.list_monom.gonext(); + } + + return res; +} + +polynom polynom::operator*(const polynom& p) const +{ + + polynom res; + polynom pth = *this; + polynom pol = p; + + pth.list_monom.Reset(); + pol.list_monom.Reset(); + + while (!pth.list_monom.IsOver()) + { + double pth_cff = pth.list_monom.GetCurr().cff; + int pth_svr = pth.list_monom.GetCurr().svr; + polynom tp(p); + tp.list_monom.Reset(); + while (!tp.list_monom.IsOver()) + { + int tp_svr = tp.list_monom.GetCurr().svr; + if ((tp_svr % 10 + pth_svr % 10) < 10 && (tp_svr / 10 % 10 + pth_svr / 10 % 10) < 10 && (tp_svr / 100 + pth_svr / 100) < 10) //îñòàòîê îò äåëåíèÿ + { + tp.list_monom.GetCurr().svr += pth_svr; + tp.list_monom.GetCurr().cff *= pth_cff; + } + else + throw "Error"; + tp.list_monom.gonext(); + } + res = res + tp; + pth.list_monom.gonext(); + } + return res; +} + +polynom polynom::operator*(const double k) const +{ + polynom res; + res = *this; + res.list_monom.Reset(); + while (!res.list_monom.IsOver()) + { + res.list_monom.GetCurr().cff *= k; + res.list_monom.gonext(); + } + return res; +} + +ostream& operator<<(ostream &str, const polynom& p) +{ + polynom pl = p; + pl.list_monom.Reset(); + + while (!pl.list_monom.IsOver()) + { + + monom tp = pl.list_monom.GetCurr(); + + if (tp.cff > 0) + { + str << "+"; + if (tp.cff == 1 && tp.svr == 0) + str << "1"; + else + if (tp.cff != 1) + str << tp.cff; + } + else + str << tp.cff; + + int a = tp.svr / 100; + if (a>1) + str << "x^" << a; + else + if (a == 1) + str << "x"; + a = tp.svr / 10 % 10; + if (a>1) + str << "y^" << a; + else + if (a == 1) + str << "y"; + a = tp.svr % 10; + if (a>1) + str << "z^" << a; + else + if (a == 1) + str << "z"; + pl.list_monom.gonext(); + } + return str; +} diff --git a/ZaharovaDD/lab2/src/table.cpp b/ZaharovaDD/lab2/src/table.cpp new file mode 100644 index 000000000..80d9d97d4 --- /dev/null +++ b/ZaharovaDD/lab2/src/table.cpp @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/ZaharovaDD/lab2/src/tableHash.cpp b/ZaharovaDD/lab2/src/tableHash.cpp new file mode 100644 index 000000000..837611b8e --- /dev/null +++ b/ZaharovaDD/lab2/src/tableHash.cpp @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/ZaharovaDD/lab2/src/tableOrder.cpp b/ZaharovaDD/lab2/src/tableOrder.cpp new file mode 100644 index 000000000..c727f87d8 --- /dev/null +++ b/ZaharovaDD/lab2/src/tableOrder.cpp @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/ZaharovaDD/lab2/src/tableUnorder.cpp b/ZaharovaDD/lab2/src/tableUnorder.cpp new file mode 100644 index 000000000..04c2dd530 --- /dev/null +++ b/ZaharovaDD/lab2/src/tableUnorder.cpp @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/ZaharovaDD/lab2/test/test_list.cpp b/ZaharovaDD/lab2/test/test_list.cpp new file mode 100644 index 000000000..ba16d596d --- /dev/null +++ b/ZaharovaDD/lab2/test/test_list.cpp @@ -0,0 +1,136 @@ +#include "gtest.h" +#include "list.h" + +TEST(lists, create_empty_list) +{ + ASSERT_NO_THROW(list m); +} + +class List : public ::testing::Test { +protected: + list l; + list l2; + +public: + List() + { + l2.InsertInOrder(10); + l2.InsertInOrder(15); + } + + ~List() {} +}; + +TEST_F(List, created_empty_list_is_correct) +{ + EXPECT_EQ(true, l.IsEmpty()); +} + +TEST_F(List, copy_empty_list) +{ + ASSERT_NO_THROW(list n(l)); +} + +TEST_F(List, copied_empty_list_is_correct) +{ + list n(l); + EXPECT_EQ(true, n.IsEmpty()); +} + +TEST_F(List, assign_empty_list) +{ + ASSERT_NO_THROW(list n = l); +} + +TEST_F(List, assigned_empty_list_is_correct) +{ + list n = l; + EXPECT_EQ(true, n.IsEmpty()); +} + +TEST_F(List, insert_in_empty_list) +{ + ASSERT_NO_THROW(l.InsertInOrder(10)); +} + +TEST_F(List, insert_in_empty_list_is_correct) +{ + l.InsertInOrder(10); + l.Reset(); + EXPECT_EQ(10, l.GetCurr()); + l.gonext(); + l.gonext(); + EXPECT_EQ(l.GetCurr(), l.GetCurr()); +} + +TEST_F(List, compare_list_with_itself) +{ + EXPECT_EQ(true, l == l); +} + +TEST_F(List, empty_lists_are_equal) +{ + list n(l); + EXPECT_EQ(true, n == l); +} + +TEST_F(List, copy_full_list) +{ + ASSERT_NO_THROW(list n(l2)); +} + +TEST_F(List, assign_full_list) +{ + ASSERT_NO_THROW(list n = l2); +} + +TEST_F(List, insert_in_the_beginning) +{ + l2.InsertInOrder(0); + l2.Reset(); + EXPECT_EQ(0, l2.GetCurr()); + l2.gonext(); + EXPECT_EQ(10, l2.GetCurr()); + l2.Reset(); + EXPECT_EQ(0, l2.GetCurr()); +} + +TEST_F(List, insert_in_the_middle) +{ + l2.InsertInOrder(15); + l2.Reset(); + EXPECT_EQ(10, l2.GetCurr()); + l2.gonext(); + EXPECT_EQ(15, l2.GetCurr()); + EXPECT_EQ(15, l2.GetCurr()); +} + + +TEST_F(List, full_lists_are_equal1) +{ + list n(l2); + EXPECT_EQ(true, n == l2); +} + +TEST_F(List, full_lists_are_equal2) +{ + list n(l2); + EXPECT_EQ(true, n == l2); +} + +TEST_F(List, full_lists_are_equal3) +{ + list n(l2); + EXPECT_EQ(true, n == l2); +} + +TEST_F(List, empty_and_full_lists_are_not_equal) +{ + EXPECT_NE(true, l2 == l); +} + +TEST_F(List, lists_with_different_sizes_and_same_beginnings_are_not_equal) +{ + l.InsertInOrder(1); + EXPECT_NE(true, l2 == l); +} \ No newline at end of file diff --git a/ZaharovaDD/lab2/test/test_main.cpp b/ZaharovaDD/lab2/test/test_main.cpp new file mode 100644 index 000000000..c0e7e7ade --- /dev/null +++ b/ZaharovaDD/lab2/test/test_main.cpp @@ -0,0 +1,5 @@ +#include +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/ZaharovaDD/lab2/test/test_polynom.cpp b/ZaharovaDD/lab2/test/test_polynom.cpp new file mode 100644 index 000000000..d7bffd430 --- /dev/null +++ b/ZaharovaDD/lab2/test/test_polynom.cpp @@ -0,0 +1,146 @@ +#include "gtest.h" +#include "polynom.h" + + +using namespace std; +TEST(polynom, check_build_polinom) +{ + + ASSERT_NO_THROW(polynom a("x+2")); +} + + +TEST(polynom, degree_not_more_than_9_1) +{ + polynom a("x^5"), b("x^4"); + ASSERT_NO_THROW(a*b); +} + +struct parse_test +{ + string str; + polynom res; + parse_test(string istr, const vector &ms) + { + str = istr; + list temp; + for (int i = 0; i < ms.size(); i++) + temp.InsertInOrder(ms[i]); + res = polynom(temp); + } +}; + +class pol_parse : public ::testing::TestWithParam +{ +protected: polynom a_test; +public: + pol_parse() : a_test(GetParam().str) + { + } + ~pol_parse() {} +}; + +TEST_P(pol_parse, correct_parse_of_polynom_strings) +{ + EXPECT_EQ(GetParam().res, a_test); +} + + +struct calc_test +{ + string left; + string right; + double c; + string res; + calc_test(string ires, string il, string ir = "", double ic = 0) + { + left = il; + right = ir; + c = ic; + res = ires; + } +}; + + + + +class pol_plus : public ::testing::TestWithParam +{ +protected: polynom pl, pr, pres; +public: + pol_plus() : pl(GetParam().left), pr(GetParam().right), pres(GetParam().res) + { + } + ~pol_plus() {} +}; + +TEST_P(pol_plus, polynom_plus_polynom) +{ + EXPECT_EQ(pres, pl + pr); +} + +INSTANTIATE_TEST_CASE_P(Inst2, + pol_plus, + ::testing::Values( + calc_test("x+y", "x", "y"), + calc_test("10x", "10x", ""), + calc_test("2x", "-4x", "6x"), + calc_test("", "-20.5xy", "20.5xy"), + calc_test("10xy^2", "7x^2y", "10xy^2-7x^2y"), + calc_test("1+x+2y+3z", "1+x+2y", "3z"), + calc_test("", "10.1", "-10.1"), + calc_test("", "0", "0"), + calc_test("0", "2.7z", "-2.7z"), + calc_test("2x-15y+30", "x", "-15y+30+x") + )); + +TEST(polynom, power_is_more_than_9_while_mult) +{ + polynom a("x^5"), b("x^5"); + ASSERT_ANY_THROW(a*b); +} + + + + +class pol_mult : public ::testing::TestWithParam +{ +protected: polynom pl, pr, pres; +public: + pol_mult() : pl(GetParam().left), pr(GetParam().right), pres(GetParam().res) + { + } + ~pol_mult() {} +}; + +TEST_P(pol_mult, polynom_mult_polynom) +{ + EXPECT_EQ(pres, pl * pr); +} + +INSTANTIATE_TEST_CASE_P(Inst3, + pol_mult, + ::testing::Values( + calc_test("xy", "x", "y"), + calc_test("25", "5", "5"), + calc_test("20xy^3", "5y^3", "4x"), + calc_test("3x+3y^2+3x^2-3xy^2-6y^4", "3+3x-6y^2", "x+y^2"), + calc_test("x^2y^2", "-x^2", "-y^2"), + calc_test("x^2y^2z+x^2y^2z^2", "xyz", "xyz+xy"), + calc_test("9-x^2", "3-x", "3+x"), + calc_test("xy+x^2y^2+x^3+y^3", "x^2+y", "x+y^2") + )); + + + + +class c_mult : public ::testing::TestWithParam +{ +protected: polynom p, pres; double cn; +public: + c_mult() : p(GetParam().left), pres(GetParam().res) + { + cn = GetParam().c; + } + ~c_mult() {} +}; \ No newline at end of file diff --git a/ZaharovaDD/lab2/test/test_table.cpp b/ZaharovaDD/lab2/test/test_table.cpp new file mode 100644 index 000000000..40a6ec92e --- /dev/null +++ b/ZaharovaDD/lab2/test/test_table.cpp @@ -0,0 +1,197 @@ +#include "monom.h" +#include "list.h" +#include "gtest.h" + +#include "tableHash.h" +#include "tableUnorder.h" +#include "table.h" +#include "tableOrder.h" +#include "polynom.h" + + +TEST(ScanTable, can_create) +{ + TableUnorder A(20); + polynom a("x+1"); + ASSERT_NO_THROW(A.Insert("x+1", a)); + +} + +class Table_Check : public ::testing::Test +{ +public: + TableHash HashT; + TableOrder OrdT; + TableUnorder ScanT; + + Table_Check() : HashT(10), OrdT(10), ScanT(10) + { + HashT.Insert("x+1", polynom("x+1")); + OrdT.Insert("x+1", polynom("x+1")); + ScanT.Insert("x+1", polynom("x+1")); + HashT.Insert("10+xyz", polynom("10+xyz")); + OrdT.Insert("10+xyz", polynom("10+xyz")); + ScanT.Insert("10+xyz", polynom("10+xyz")); + HashT.Insert("x^4", polynom("x^4")); + OrdT.Insert("x^4", polynom("x^4")); + ScanT.Insert("x^4", polynom("x^4")); + }; + +}; + + +TEST_F(Table_Check, can_GetCur_ScanT) +{ + ScanT.Reset(); + polynom p("x+1"); + EXPECT_EQ(ScanT.GetCurr(), p); +} + +TEST_F(Table_Check, can_gonext_OrdT) +{ + ASSERT_NO_THROW(OrdT.GoNext()); +} + +TEST_F(Table_Check, can_gonext_HashT) +{ + ASSERT_NO_THROW(HashT.GoNext()); +} + +TEST_F(Table_Check, can_get_next_ScanT) +{ + ASSERT_NO_THROW(ScanT.GoNext()); +} + +TEST_F(Table_Check, can_Search_existed_element_HashT) +{ + EXPECT_EQ(HashT.Search("x+1")->data, polynom("x+1")); +} + +TEST_F(Table_Check, can_Search_existed_element_ScanT) +{ + EXPECT_EQ(ScanT.Search("x+1")->data, polynom("x+1")); +} + +TEST_F(Table_Check, can_Search_existed_element_OrdT) +{ + EXPECT_EQ(OrdT.Search("x+1")->data, polynom("x+1")); +} + +TEST_F(Table_Check, can_Delete_existed_element_HashT) +{ + HashT.Dell("x+1"); + ASSERT_ANY_THROW(HashT.Search("x+1")); +} + +TEST_F(Table_Check, can_Delete_existed_element_ScanT) +{ + ScanT.Dell("x+1"); + ASSERT_ANY_THROW(ScanT.Search("x+1")); +} + +TEST_F(Table_Check, can_Delete_existed_element_OrdT) +{ + OrdT.Dell("x+1"); + ASSERT_ANY_THROW(OrdT.Search("x+1")); +} + + +TEST_F(Table_Check, can_Insert_element_ScanT) +{ + ScanT.Insert("1+z", polynom("1+z")); + EXPECT_EQ(ScanT.Search("1+z")->data, polynom("1+z")); +} + +TEST_F(Table_Check, can_Insert_element_OrdT) +{ + OrdT.Insert("xyz+z^5", polynom("xyz+z^5")); + EXPECT_EQ(OrdT.Search("xyz+z^5")->data, polynom("xyz+z^5")); +} + +TEST_F(Table_Check, can_Search_existed_element_ScanT2) +{ + EXPECT_EQ(ScanT.Search("10+xyz")->data, polynom("10+xyz")); +} + +TEST_F(Table_Check, can_Search_existed_element_OrdT2) +{ + EXPECT_EQ(OrdT.Search("10+xyz")->data, polynom("10+xyz")); +} + +TEST_F(Table_Check, can_Search_existed_element_HashT3) +{ + EXPECT_EQ(HashT.Search("x^4")->data, polynom("x^4")); +} + +TEST_F(Table_Check, can_Search_existed_element_ScanT3) +{ + EXPECT_EQ(ScanT.Search("x^4")->data, polynom("x^4")); +} + +TEST_F(Table_Check, can_Search_existed_element_OrdT3) +{ + EXPECT_EQ(OrdT.Search("x^4")->data, polynom("x^4")); +} + +TEST_F(Table_Check, can_Insert_element_HashT2) +{ + HashT.Insert("111+z", polynom("111+z")); + EXPECT_EQ(HashT.Search("111+z")->data, polynom("111+z")); +} + +TEST_F(Table_Check, can_Insert_element_ScanT2) +{ + ScanT.Insert("1+32.1x", polynom("1+32.1x")); + EXPECT_EQ(ScanT.Search("1+32.1x")->data, polynom("1+32.1x")); +} + +TEST_F(Table_Check, can_Insert_element_OrdT2) +{ + OrdT.Insert("xyz", polynom("xyz")); + EXPECT_EQ(OrdT.Search("xyz")->data, polynom("xyz")); +} + +TEST_F(Table_Check, cannot_Delete_element_HashT) +{ + ASSERT_ANY_THROW(HashT.Dell("12")); +} + +TEST_F(Table_Check, cannot_Delete_element_ScanT) +{ + ASSERT_ANY_THROW(ScanT.Dell("12")); +} + +TEST_F(Table_Check, cannot_Delete_element_OrdT) +{ + ASSERT_ANY_THROW(OrdT.Dell("12")); +} + +TEST_F(Table_Check, cannot_Inset_ex_element_ScanT) +{ + ASSERT_ANY_THROW(ScanT.Insert("x+1", polynom("x+1"))); +} + +TEST_F(Table_Check, cannot_Inset_ex_element_OrdT) +{ + ASSERT_ANY_THROW(OrdT.Insert("x+1", polynom("x+1"))); +} + +TEST_F(Table_Check, cannot_Inset_ex_element_ScanT2) +{ + ASSERT_ANY_THROW(ScanT.Insert("x^4", polynom("x+1"))); +} + +TEST_F(Table_Check, cannot_Inset_ex_element_OrdT2) +{ + ASSERT_ANY_THROW(OrdT.Insert("x^4", polynom("x+1"))); +} + +TEST_F(Table_Check, can_Delete_OrdT) +{ + ASSERT_ANY_THROW(OrdT.Dell("100")); +} + +TEST_F(Table_Check, can_Delete_Ord2T) +{ + ASSERT_ANY_THROW(OrdT.Dell("10")); +} \ No newline at end of file From 907fcff78aad9063bb4b41a122b9b071bb8f4500 Mon Sep 17 00:00:00 2001 From: zaharovadasha Date: Mon, 4 Jun 2018 22:23:11 +0300 Subject: [PATCH 6/7] itog --- ZaharovaDD/lab2/otchet_table.docx | Bin 124816 -> 124867 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/ZaharovaDD/lab2/otchet_table.docx b/ZaharovaDD/lab2/otchet_table.docx index 1d1dd694171d124fc917c53077437575011b9d34..170abfb2d3aea3e9f8d95c1ecfdfaac68703800e 100644 GIT binary patch delta 58744 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 P%07S=adq?UEzJJ_l4o-6 From ce856b87d60e66d9aed9957498714463eb22f4e2 Mon Sep 17 00:00:00 2001 From: zaharovadasha Date: Mon, 4 Jun 2018 22:59:07 +0300 Subject: [PATCH 7/7] itog --- ZaharovaDD/lab1/otchet_polynom.docx | Bin 113363 -> 114908 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/ZaharovaDD/lab1/otchet_polynom.docx b/ZaharovaDD/lab1/otchet_polynom.docx index 4c61763cef208221a09dd15de6fecc1e66d0a299..4411839bb6f39ef8b6fb313f0afe1e548dae24e3 100644 GIT binary patch delta 52741 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 delta 51180 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