gtest-param-util.h (googletest-release-1.10.0) | : | gtest-param-util.h (googletest-release-1.11.0) | ||
---|---|---|---|---|
skipping to change at line 34 | skipping to change at line 34 | |||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
// Type and function utilities for implementing parameterized tests. | // Type and function utilities for implementing parameterized tests. | |||
// GOOGLETEST_CM0001 DO NOT DELETE | // GOOGLETEST_CM0001 DO NOT DELETE | |||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ | #ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ | |||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ | #define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ | |||
#include <ctype.h> | #include <ctype.h> | |||
#include <cassert> | #include <cassert> | |||
#include <iterator> | #include <iterator> | |||
#include <memory> | #include <memory> | |||
#include <set> | #include <set> | |||
#include <tuple> | #include <tuple> | |||
#include <type_traits> | ||||
#include <utility> | #include <utility> | |||
#include <vector> | #include <vector> | |||
#include "gtest/internal/gtest-internal.h" | #include "gtest/internal/gtest-internal.h" | |||
#include "gtest/internal/gtest-port.h" | #include "gtest/internal/gtest-port.h" | |||
#include "gtest/gtest-printers.h" | #include "gtest/gtest-printers.h" | |||
#include "gtest/gtest-test-part.h" | ||||
namespace testing { | namespace testing { | |||
// Input to a parameterized test name generator, describing a test parameter. | // Input to a parameterized test name generator, describing a test parameter. | |||
// Consists of the parameter value and the integer parameter index. | // Consists of the parameter value and the integer parameter index. | |||
template <class ParamType> | template <class ParamType> | |||
struct TestParamInfo { | struct TestParamInfo { | |||
TestParamInfo(const ParamType& a_param, size_t an_index) : | TestParamInfo(const ParamType& a_param, size_t an_index) : | |||
param(a_param), | param(a_param), | |||
index(an_index) {} | index(an_index) {} | |||
ParamType param; | ParamType param; | |||
skipping to change at line 458 | skipping to change at line 460 | |||
// and uses that information to register all resulting test instances | // and uses that information to register all resulting test instances | |||
// in RegisterTests method. The ParameterizeTestSuiteRegistry class holds | // in RegisterTests method. The ParameterizeTestSuiteRegistry class holds | |||
// a collection of pointers to the ParameterizedTestSuiteInfo objects | // a collection of pointers to the ParameterizedTestSuiteInfo objects | |||
// and calls RegisterTests() on each of them when asked. | // and calls RegisterTests() on each of them when asked. | |||
class ParameterizedTestSuiteInfoBase { | class ParameterizedTestSuiteInfoBase { | |||
public: | public: | |||
virtual ~ParameterizedTestSuiteInfoBase() {} | virtual ~ParameterizedTestSuiteInfoBase() {} | |||
// Base part of test suite name for display purposes. | // Base part of test suite name for display purposes. | |||
virtual const std::string& GetTestSuiteName() const = 0; | virtual const std::string& GetTestSuiteName() const = 0; | |||
// Test case id to verify identity. | // Test suite id to verify identity. | |||
virtual TypeId GetTestSuiteTypeId() const = 0; | virtual TypeId GetTestSuiteTypeId() const = 0; | |||
// UnitTest class invokes this method to register tests in this | // UnitTest class invokes this method to register tests in this | |||
// test suite right before running them in RUN_ALL_TESTS macro. | // test suite right before running them in RUN_ALL_TESTS macro. | |||
// This method should not be called more than once on any single | // This method should not be called more than once on any single | |||
// instance of a ParameterizedTestSuiteInfoBase derived class. | // instance of a ParameterizedTestSuiteInfoBase derived class. | |||
virtual void RegisterTests() = 0; | virtual void RegisterTests() = 0; | |||
protected: | protected: | |||
ParameterizedTestSuiteInfoBase() {} | ParameterizedTestSuiteInfoBase() {} | |||
private: | private: | |||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfoBase); | GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfoBase); | |||
}; | }; | |||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. | // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. | |||
// | // | |||
// Report a the name of a test_suit as safe to ignore | ||||
// as the side effect of construction of this type. | ||||
struct GTEST_API_ MarkAsIgnored { | ||||
explicit MarkAsIgnored(const char* test_suite); | ||||
}; | ||||
GTEST_API_ void InsertSyntheticTestCase(const std::string& name, | ||||
CodeLocation location, bool has_test_p); | ||||
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. | ||||
// | ||||
// ParameterizedTestSuiteInfo accumulates tests obtained from TEST_P | // ParameterizedTestSuiteInfo accumulates tests obtained from TEST_P | |||
// macro invocations for a particular test suite and generators | // macro invocations for a particular test suite and generators | |||
// obtained from INSTANTIATE_TEST_SUITE_P macro invocations for that | // obtained from INSTANTIATE_TEST_SUITE_P macro invocations for that | |||
// test suite. It registers tests with all values generated by all | // test suite. It registers tests with all values generated by all | |||
// generators when asked. | // generators when asked. | |||
template <class TestSuite> | template <class TestSuite> | |||
class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { | class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { | |||
public: | public: | |||
// ParamType and GeneratorCreationFunc are private types but are required | // ParamType and GeneratorCreationFunc are private types but are required | |||
// for declarations of public methods AddTestPattern() and | // for declarations of public methods AddTestPattern() and | |||
// AddTestSuiteInstantiation(). | // AddTestSuiteInstantiation(). | |||
using ParamType = typename TestSuite::ParamType; | using ParamType = typename TestSuite::ParamType; | |||
// A function that returns an instance of appropriate generator type. | // A function that returns an instance of appropriate generator type. | |||
typedef ParamGenerator<ParamType>(GeneratorCreationFunc)(); | typedef ParamGenerator<ParamType>(GeneratorCreationFunc)(); | |||
using ParamNameGeneratorFunc = std::string(const TestParamInfo<ParamType>&); | using ParamNameGeneratorFunc = std::string(const TestParamInfo<ParamType>&); | |||
explicit ParameterizedTestSuiteInfo(const char* name, | explicit ParameterizedTestSuiteInfo(const char* name, | |||
CodeLocation code_location) | CodeLocation code_location) | |||
: test_suite_name_(name), code_location_(code_location) {} | : test_suite_name_(name), code_location_(code_location) {} | |||
// Test case base name for display purposes. | // Test suite base name for display purposes. | |||
const std::string& GetTestSuiteName() const override { | const std::string& GetTestSuiteName() const override { | |||
return test_suite_name_; | return test_suite_name_; | |||
} | } | |||
// Test case id to verify identity. | // Test suite id to verify identity. | |||
TypeId GetTestSuiteTypeId() const override { return GetTypeId<TestSuite>(); } | TypeId GetTestSuiteTypeId() const override { return GetTypeId<TestSuite>(); } | |||
// TEST_P macro uses AddTestPattern() to record information | // TEST_P macro uses AddTestPattern() to record information | |||
// about a single test in a LocalTestInfo structure. | // about a single test in a LocalTestInfo structure. | |||
// test_suite_name is the base name of the test suite (without invocation | // test_suite_name is the base name of the test suite (without invocation | |||
// prefix). test_base_name is the name of an individual test without | // prefix). test_base_name is the name of an individual test without | |||
// parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is | // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is | |||
// test suite base name and DoBar is test base name. | // test suite base name and DoBar is test base name. | |||
void AddTestPattern(const char* test_suite_name, const char* test_base_name, | void AddTestPattern(const char* test_suite_name, const char* test_base_name, | |||
TestMetaFactoryBase<ParamType>* meta_factory) { | TestMetaFactoryBase<ParamType>* meta_factory, | |||
tests_.push_back(std::shared_ptr<TestInfo>( | CodeLocation code_location) { | |||
new TestInfo(test_suite_name, test_base_name, meta_factory))); | tests_.push_back(std::shared_ptr<TestInfo>(new TestInfo( | |||
test_suite_name, test_base_name, meta_factory, code_location))); | ||||
} | } | |||
// INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information | // INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information | |||
// about a generator. | // about a generator. | |||
int AddTestSuiteInstantiation(const std::string& instantiation_name, | int AddTestSuiteInstantiation(const std::string& instantiation_name, | |||
GeneratorCreationFunc* func, | GeneratorCreationFunc* func, | |||
ParamNameGeneratorFunc* name_func, | ParamNameGeneratorFunc* name_func, | |||
const char* file, int line) { | const char* file, int line) { | |||
instantiations_.push_back( | instantiations_.push_back( | |||
InstantiationInfo(instantiation_name, func, name_func, file, line)); | InstantiationInfo(instantiation_name, func, name_func, file, line)); | |||
return 0; // Return value used only to run this method in namespace scope. | return 0; // Return value used only to run this method in namespace scope. | |||
} | } | |||
// UnitTest class invokes this method to register tests in this test suite | // UnitTest class invokes this method to register tests in this test suite | |||
// test suites right before running tests in RUN_ALL_TESTS macro. | // right before running tests in RUN_ALL_TESTS macro. | |||
// This method should not be called more than once on any single | // This method should not be called more than once on any single | |||
// instance of a ParameterizedTestSuiteInfoBase derived class. | // instance of a ParameterizedTestSuiteInfoBase derived class. | |||
// UnitTest has a guard to prevent from calling this method more than once. | // UnitTest has a guard to prevent from calling this method more than once. | |||
void RegisterTests() override { | void RegisterTests() override { | |||
bool generated_instantiations = false; | ||||
for (typename TestInfoContainer::iterator test_it = tests_.begin(); | for (typename TestInfoContainer::iterator test_it = tests_.begin(); | |||
test_it != tests_.end(); ++test_it) { | test_it != tests_.end(); ++test_it) { | |||
std::shared_ptr<TestInfo> test_info = *test_it; | std::shared_ptr<TestInfo> test_info = *test_it; | |||
for (typename InstantiationContainer::iterator gen_it = | for (typename InstantiationContainer::iterator gen_it = | |||
instantiations_.begin(); gen_it != instantiations_.end(); | instantiations_.begin(); gen_it != instantiations_.end(); | |||
++gen_it) { | ++gen_it) { | |||
const std::string& instantiation_name = gen_it->name; | const std::string& instantiation_name = gen_it->name; | |||
ParamGenerator<ParamType> generator((*gen_it->generator)()); | ParamGenerator<ParamType> generator((*gen_it->generator)()); | |||
ParamNameGeneratorFunc* name_func = gen_it->name_func; | ParamNameGeneratorFunc* name_func = gen_it->name_func; | |||
const char* file = gen_it->file; | const char* file = gen_it->file; | |||
skipping to change at line 550 | skipping to change at line 566 | |||
std::string test_suite_name; | std::string test_suite_name; | |||
if ( !instantiation_name.empty() ) | if ( !instantiation_name.empty() ) | |||
test_suite_name = instantiation_name + "/"; | test_suite_name = instantiation_name + "/"; | |||
test_suite_name += test_info->test_suite_base_name; | test_suite_name += test_info->test_suite_base_name; | |||
size_t i = 0; | size_t i = 0; | |||
std::set<std::string> test_param_names; | std::set<std::string> test_param_names; | |||
for (typename ParamGenerator<ParamType>::iterator param_it = | for (typename ParamGenerator<ParamType>::iterator param_it = | |||
generator.begin(); | generator.begin(); | |||
param_it != generator.end(); ++param_it, ++i) { | param_it != generator.end(); ++param_it, ++i) { | |||
generated_instantiations = true; | ||||
Message test_name_stream; | Message test_name_stream; | |||
std::string param_name = name_func( | std::string param_name = name_func( | |||
TestParamInfo<ParamType>(*param_it, i)); | TestParamInfo<ParamType>(*param_it, i)); | |||
GTEST_CHECK_(IsValidParamName(param_name)) | GTEST_CHECK_(IsValidParamName(param_name)) | |||
<< "Parameterized test name '" << param_name | << "Parameterized test name '" << param_name | |||
<< "' is invalid, in " << file | << "' is invalid, in " << file | |||
<< " line " << line << std::endl; | << " line " << line << std::endl; | |||
skipping to change at line 573 | skipping to change at line 591 | |||
test_param_names.insert(param_name); | test_param_names.insert(param_name); | |||
if (!test_info->test_base_name.empty()) { | if (!test_info->test_base_name.empty()) { | |||
test_name_stream << test_info->test_base_name << "/"; | test_name_stream << test_info->test_base_name << "/"; | |||
} | } | |||
test_name_stream << param_name; | test_name_stream << param_name; | |||
MakeAndRegisterTestInfo( | MakeAndRegisterTestInfo( | |||
test_suite_name.c_str(), test_name_stream.GetString().c_str(), | test_suite_name.c_str(), test_name_stream.GetString().c_str(), | |||
nullptr, // No type parameter. | nullptr, // No type parameter. | |||
PrintToString(*param_it).c_str(), code_location_, | PrintToString(*param_it).c_str(), test_info->code_location, | |||
GetTestSuiteTypeId(), | GetTestSuiteTypeId(), | |||
SuiteApiResolver<TestSuite>::GetSetUpCaseOrSuite(file, line), | SuiteApiResolver<TestSuite>::GetSetUpCaseOrSuite(file, line), | |||
SuiteApiResolver<TestSuite>::GetTearDownCaseOrSuite(file, line), | SuiteApiResolver<TestSuite>::GetTearDownCaseOrSuite(file, line), | |||
test_info->test_meta_factory->CreateTestFactory(*param_it)); | test_info->test_meta_factory->CreateTestFactory(*param_it)); | |||
} // for param_it | } // for param_it | |||
} // for gen_it | } // for gen_it | |||
} // for test_it | } // for test_it | |||
if (!generated_instantiations) { | ||||
// There are no generaotrs, or they all generate nothing ... | ||||
InsertSyntheticTestCase(GetTestSuiteName(), code_location_, | ||||
!tests_.empty()); | ||||
} | ||||
} // RegisterTests | } // RegisterTests | |||
private: | private: | |||
// LocalTestInfo structure keeps information about a single test registered | // LocalTestInfo structure keeps information about a single test registered | |||
// with TEST_P macro. | // with TEST_P macro. | |||
struct TestInfo { | struct TestInfo { | |||
TestInfo(const char* a_test_suite_base_name, const char* a_test_base_name, | TestInfo(const char* a_test_suite_base_name, const char* a_test_base_name, | |||
TestMetaFactoryBase<ParamType>* a_test_meta_factory) | TestMetaFactoryBase<ParamType>* a_test_meta_factory, | |||
CodeLocation a_code_location) | ||||
: test_suite_base_name(a_test_suite_base_name), | : test_suite_base_name(a_test_suite_base_name), | |||
test_base_name(a_test_base_name), | test_base_name(a_test_base_name), | |||
test_meta_factory(a_test_meta_factory) {} | test_meta_factory(a_test_meta_factory), | |||
code_location(a_code_location) {} | ||||
const std::string test_suite_base_name; | const std::string test_suite_base_name; | |||
const std::string test_base_name; | const std::string test_base_name; | |||
const std::unique_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory; | const std::unique_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory; | |||
const CodeLocation code_location; | ||||
}; | }; | |||
using TestInfoContainer = ::std::vector<std::shared_ptr<TestInfo> >; | using TestInfoContainer = ::std::vector<std::shared_ptr<TestInfo> >; | |||
// Records data received from INSTANTIATE_TEST_SUITE_P macros: | // Records data received from INSTANTIATE_TEST_SUITE_P macros: | |||
// <Instantiation name, Sequence generator creation function, | // <Instantiation name, Sequence generator creation function, | |||
// Name generator function, Source file, Source line> | // Name generator function, Source file, Source line> | |||
struct InstantiationInfo { | struct InstantiationInfo { | |||
InstantiationInfo(const std::string &name_in, | InstantiationInfo(const std::string &name_in, | |||
GeneratorCreationFunc* generator_in, | GeneratorCreationFunc* generator_in, | |||
ParamNameGeneratorFunc* name_func_in, | ParamNameGeneratorFunc* name_func_in, | |||
const char* file_in, | const char* file_in, | |||
skipping to change at line 628 | skipping to change at line 655 | |||
}; | }; | |||
typedef ::std::vector<InstantiationInfo> InstantiationContainer; | typedef ::std::vector<InstantiationInfo> InstantiationContainer; | |||
static bool IsValidParamName(const std::string& name) { | static bool IsValidParamName(const std::string& name) { | |||
// Check for empty string | // Check for empty string | |||
if (name.empty()) | if (name.empty()) | |||
return false; | return false; | |||
// Check for invalid characters | // Check for invalid characters | |||
for (std::string::size_type index = 0; index < name.size(); ++index) { | for (std::string::size_type index = 0; index < name.size(); ++index) { | |||
if (!isalnum(name[index]) && name[index] != '_') | if (!IsAlNum(name[index]) && name[index] != '_') | |||
return false; | return false; | |||
} | } | |||
return true; | return true; | |||
} | } | |||
const std::string test_suite_name_; | const std::string test_suite_name_; | |||
CodeLocation code_location_; | CodeLocation code_location_; | |||
TestInfoContainer tests_; | TestInfoContainer tests_; | |||
InstantiationContainer instantiations_; | InstantiationContainer instantiations_; | |||
skipping to change at line 718 | skipping to change at line 745 | |||
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ | #endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ | |||
private: | private: | |||
using TestSuiteInfoContainer = ::std::vector<ParameterizedTestSuiteInfoBase*>; | using TestSuiteInfoContainer = ::std::vector<ParameterizedTestSuiteInfoBase*>; | |||
TestSuiteInfoContainer test_suite_infos_; | TestSuiteInfoContainer test_suite_infos_; | |||
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteRegistry); | GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteRegistry); | |||
}; | }; | |||
// Keep track of what type-parameterized test suite are defined and | ||||
// where as well as which are intatiated. This allows susequently | ||||
// identifying suits that are defined but never used. | ||||
class TypeParameterizedTestSuiteRegistry { | ||||
public: | ||||
// Add a suite definition | ||||
void RegisterTestSuite(const char* test_suite_name, | ||||
CodeLocation code_location); | ||||
// Add an instantiation of a suit. | ||||
void RegisterInstantiation(const char* test_suite_name); | ||||
// For each suit repored as defined but not reported as instantiation, | ||||
// emit a test that reports that fact (configurably, as an error). | ||||
void CheckForInstantiations(); | ||||
private: | ||||
struct TypeParameterizedTestSuiteInfo { | ||||
explicit TypeParameterizedTestSuiteInfo(CodeLocation c) | ||||
: code_location(c), instantiated(false) {} | ||||
CodeLocation code_location; | ||||
bool instantiated; | ||||
}; | ||||
std::map<std::string, TypeParameterizedTestSuiteInfo> suites_; | ||||
}; | ||||
} // namespace internal | } // namespace internal | |||
// Forward declarations of ValuesIn(), which is implemented in | // Forward declarations of ValuesIn(), which is implemented in | |||
// include/gtest/gtest-param-test.h. | // include/gtest/gtest-param-test.h. | |||
template <class Container> | template <class Container> | |||
internal::ParamGenerator<typename Container::value_type> ValuesIn( | internal::ParamGenerator<typename Container::value_type> ValuesIn( | |||
const Container& container); | const Container& container); | |||
namespace internal { | namespace internal { | |||
// Used in the Values() function to provide polymorphic capabilities. | // Used in the Values() function to provide polymorphic capabilities. | |||
#ifdef _MSC_VER | ||||
#pragma warning(push) | ||||
#pragma warning(disable : 4100) | ||||
#endif | ||||
template <typename... Ts> | template <typename... Ts> | |||
class ValueArray { | class ValueArray { | |||
public: | public: | |||
ValueArray(Ts... v) : v_{std::move(v)...} {} | explicit ValueArray(Ts... v) : v_(FlatTupleConstructTag{}, std::move(v)...) {} | |||
template <typename T> | template <typename T> | |||
operator ParamGenerator<T>() const { // NOLINT | operator ParamGenerator<T>() const { // NOLINT | |||
return ValuesIn(MakeVector<T>(MakeIndexSequence<sizeof...(Ts)>())); | return ValuesIn(MakeVector<T>(MakeIndexSequence<sizeof...(Ts)>())); | |||
} | } | |||
private: | private: | |||
template <typename T, size_t... I> | template <typename T, size_t... I> | |||
std::vector<T> MakeVector(IndexSequence<I...>) const { | std::vector<T> MakeVector(IndexSequence<I...>) const { | |||
return std::vector<T>{static_cast<T>(v_.template Get<I>())...}; | return std::vector<T>{static_cast<T>(v_.template Get<I>())...}; | |||
} | } | |||
FlatTuple<Ts...> v_; | FlatTuple<Ts...> v_; | |||
}; | }; | |||
#ifdef _MSC_VER | ||||
#pragma warning(pop) | ||||
#endif | ||||
template <typename... T> | template <typename... T> | |||
class CartesianProductGenerator | class CartesianProductGenerator | |||
: public ParamGeneratorInterface<::std::tuple<T...>> { | : public ParamGeneratorInterface<::std::tuple<T...>> { | |||
public: | public: | |||
typedef ::std::tuple<T...> ParamType; | typedef ::std::tuple<T...> ParamType; | |||
CartesianProductGenerator(const std::tuple<ParamGenerator<T>...>& g) | CartesianProductGenerator(const std::tuple<ParamGenerator<T>...>& g) | |||
: generators_(g) {} | : generators_(g) {} | |||
~CartesianProductGenerator() override {} | ~CartesianProductGenerator() override {} | |||
skipping to change at line 881 | skipping to change at line 945 | |||
new CartesianProductGenerator<T...>(generators_)); | new CartesianProductGenerator<T...>(generators_)); | |||
} | } | |||
private: | private: | |||
std::tuple<Gen...> generators_; | std::tuple<Gen...> generators_; | |||
}; | }; | |||
} // namespace internal | } // namespace internal | |||
} // namespace testing | } // namespace testing | |||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ | #endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ | |||
End of changes. 22 change blocks. | ||||
14 lines changed or deleted | 78 lines changed or added |