diff options
Diffstat (limited to 'utils/unittest/googletest/include/gtest/internal/gtest-param-util.h')
-rw-r--r-- | utils/unittest/googletest/include/gtest/internal/gtest-param-util.h | 190 |
1 files changed, 151 insertions, 39 deletions
diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h b/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h index dea4d5cc6bcb..82cab9b0201b 100644 --- a/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h +++ b/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h @@ -34,7 +34,10 @@ #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ +#include <ctype.h> + #include <iterator> +#include <set> #include <utility> #include <vector> @@ -49,6 +52,27 @@ #if GTEST_HAS_PARAM_TEST namespace testing { + +// Input to a parameterized test name generator, describing a test parameter. +// Consists of the parameter value and the integer parameter index. +template <class ParamType> +struct TestParamInfo { + TestParamInfo(const ParamType& a_param, size_t an_index) : + param(a_param), + index(an_index) {} + ParamType param; + size_t index; +}; + +// A builtin parameterized test name generator which returns the result of +// testing::PrintToString. +struct PrintToStringParamName { + template <class ParamType> + std::string operator()(const TestParamInfo<ParamType>& info) const { + return PrintToString(info.param); + } +}; + namespace internal { // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. @@ -58,7 +82,7 @@ namespace internal { // 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); + CodeLocation code_location); template <typename> class ParamGeneratorInterface; template <typename> class ParamGenerator; @@ -206,7 +230,7 @@ class RangeGenerator : public ParamGeneratorInterface<T> { return base_; } virtual void Advance() { - value_ = value_ + step_; + value_ = static_cast<T>(value_ + step_); index_++; } virtual ParamIteratorInterface<T>* Clone() const { @@ -243,7 +267,7 @@ class RangeGenerator : public ParamGeneratorInterface<T> { const T& end, const IncrementT& step) { int end_index = 0; - for (T i = begin; i < end; i = i + step) + for (T i = begin; i < end; i = static_cast<T>(i + step)) end_index++; return end_index; } @@ -270,12 +294,12 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> { template <typename ForwardIterator> ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end) : container_(begin, end) {} - ~ValuesInIteratorRangeGenerator() override {} + virtual ~ValuesInIteratorRangeGenerator() {} - ParamIteratorInterface<T> *Begin() const override { + virtual ParamIteratorInterface<T>* Begin() const { return new Iterator(this, container_.begin()); } - ParamIteratorInterface<T> *End() const override { + virtual ParamIteratorInterface<T>* End() const { return new Iterator(this, container_.end()); } @@ -287,16 +311,16 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> { Iterator(const ParamGeneratorInterface<T>* base, typename ContainerType::const_iterator iterator) : base_(base), iterator_(iterator) {} - ~Iterator() override {} + virtual ~Iterator() {} - const ParamGeneratorInterface<T> *BaseGenerator() const override { + virtual const ParamGeneratorInterface<T>* BaseGenerator() const { return base_; } - void Advance() override { + virtual void Advance() { ++iterator_; value_.reset(); } - ParamIteratorInterface<T> *Clone() const override { + virtual ParamIteratorInterface<T>* Clone() const { return new Iterator(*this); } // We need to use cached value referenced by iterator_ because *iterator_ @@ -306,12 +330,12 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> { // 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. - const T *Current() const override { + virtual const T* Current() const { if (value_.get() == NULL) value_.reset(new T(*iterator_)); return value_.get(); } - bool Equals(const ParamIteratorInterface<T> &other) const override { + virtual bool Equals(const ParamIteratorInterface<T>& 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()) @@ -347,6 +371,37 @@ class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> { // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // +// Default parameterized test name generator, returns a string containing the +// integer test parameter index. +template <class ParamType> +std::string DefaultParamName(const TestParamInfo<ParamType>& info) { + Message name_stream; + name_stream << info.index; + return name_stream.GetString(); +} + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Parameterized test name overload helpers, which help the +// INSTANTIATE_TEST_CASE_P macro choose between the default parameterized +// test name generator and user param name generator. +template <class ParamType, class ParamNameGenFunctor> +ParamNameGenFunctor GetParamNameGen(ParamNameGenFunctor func) { + return func; +} + +template <class ParamType> +struct ParamNameGenFunc { + typedef std::string Type(const TestParamInfo<ParamType>&); +}; + +template <class ParamType> +typename ParamNameGenFunc<ParamType>::Type *GetParamNameGen() { + return DefaultParamName; +} + +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// // Stores a parameter value and later creates tests parameterized with that // value. template <class TestClass> @@ -355,7 +410,7 @@ class ParameterizedTestFactory : public TestFactoryBase { typedef typename TestClass::ParamType ParamType; explicit ParameterizedTestFactory(ParamType parameter) : parameter_(parameter) {} - Test *CreateTest() override { + virtual Test* CreateTest() { TestClass::SetParam(¶meter_); return new TestClass(); } @@ -394,7 +449,7 @@ class TestMetaFactory TestMetaFactory() {} - TestFactoryBase *CreateTestFactory(ParamType parameter) override { + virtual TestFactoryBase* CreateTestFactory(ParamType parameter) { return new ParameterizedTestFactory<TestCase>(parameter); } @@ -414,7 +469,7 @@ class TestMetaFactory // and calls RegisterTests() on each of them when asked. class ParameterizedTestCaseInfoBase { public: - virtual ~ParameterizedTestCaseInfoBase(); + virtual ~ParameterizedTestCaseInfoBase() {} // Base part of test case name for display purposes. virtual const string& GetTestCaseName() const = 0; @@ -449,14 +504,16 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { typedef typename TestCase::ParamType ParamType; // A function that returns an instance of appropriate generator type. typedef ParamGenerator<ParamType>(GeneratorCreationFunc)(); + typedef typename ParamNameGenFunc<ParamType>::Type ParamNameGeneratorFunc; - explicit ParameterizedTestCaseInfo(const char* name) - : test_case_name_(name) {} + explicit ParameterizedTestCaseInfo( + const char* name, CodeLocation code_location) + : test_case_name_(name), code_location_(code_location) {} // Test case base name for display purposes. - const string &GetTestCaseName() const override { return test_case_name_; } + virtual const string& GetTestCaseName() const { return test_case_name_; } // Test case id to verify identity. - TypeId GetTestCaseTypeId() const override { return GetTypeId<TestCase>(); } + virtual TypeId GetTestCaseTypeId() const { return GetTypeId<TestCase>(); } // 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 @@ -474,9 +531,11 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { // 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)); + ParamNameGeneratorFunc* name_func, + const char* file, + int line) { + instantiations_.push_back( + InstantiationInfo(instantiation_name, func, name_func, file, line)); 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 @@ -484,32 +543,52 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { // 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. - void RegisterTests() override { + virtual void RegisterTests() { for (typename TestInfoContainer::iterator test_it = tests_.begin(); test_it != tests_.end(); ++test_it) { linked_ptr<TestInfo> 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<ParamType> generator((*gen_it->second)()); + const string& instantiation_name = gen_it->name; + ParamGenerator<ParamType> generator((*gen_it->generator)()); + ParamNameGeneratorFunc* name_func = gen_it->name_func; + const char* file = gen_it->file; + int line = gen_it->line; - Message test_case_name_stream; + string test_case_name; if ( !instantiation_name.empty() ) - test_case_name_stream << instantiation_name << "/"; - test_case_name_stream << test_info->test_case_base_name; + test_case_name = instantiation_name + "/"; + test_case_name += test_info->test_case_base_name; - int i = 0; + size_t i = 0; + std::set<std::string> test_param_names; for (typename ParamGenerator<ParamType>::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; + + std::string param_name = name_func( + TestParamInfo<ParamType>(*param_it, i)); + + GTEST_CHECK_(IsValidParamName(param_name)) + << "Parameterized test name '" << param_name + << "' is invalid, in " << file + << " line " << line << std::endl; + + GTEST_CHECK_(test_param_names.count(param_name) == 0) + << "Duplicate parameterized test name '" << param_name + << "', in " << file << " line " << line << std::endl; + + test_param_names.insert(param_name); + + test_name_stream << test_info->test_base_name << "/" << param_name; MakeAndRegisterTestInfo( - test_case_name_stream.GetString().c_str(), + test_case_name.c_str(), test_name_stream.GetString().c_str(), NULL, // No type parameter. PrintToString(*param_it).c_str(), + code_location_, GetTestCaseTypeId(), TestCase::SetUpTestCase, TestCase::TearDownTestCase, @@ -535,12 +614,45 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { const scoped_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory; }; typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer; - // Keeps pairs of <Instantiation name, Sequence generator creation function> - // received from INSTANTIATE_TEST_CASE_P macros. - typedef ::std::vector<std::pair<string, GeneratorCreationFunc*> > - InstantiationContainer; + // Records data received from INSTANTIATE_TEST_CASE_P macros: + // <Instantiation name, Sequence generator creation function, + // Name generator function, Source file, Source line> + struct InstantiationInfo { + InstantiationInfo(const std::string &name_in, + GeneratorCreationFunc* generator_in, + ParamNameGeneratorFunc* name_func_in, + const char* file_in, + int line_in) + : name(name_in), + generator(generator_in), + name_func(name_func_in), + file(file_in), + line(line_in) {} + + std::string name; + GeneratorCreationFunc* generator; + ParamNameGeneratorFunc* name_func; + const char* file; + int line; + }; + typedef ::std::vector<InstantiationInfo> InstantiationContainer; + + static bool IsValidParamName(const std::string& name) { + // Check for empty string + if (name.empty()) + return false; + + // Check for invalid characters + for (std::string::size_type index = 0; index < name.size(); ++index) { + if (!isalnum(name[index]) && name[index] != '_') + return false; + } + + return true; + } const string test_case_name_; + CodeLocation code_location_; TestInfoContainer tests_; InstantiationContainer instantiations_; @@ -568,8 +680,7 @@ class ParameterizedTestCaseRegistry { template <class TestCase> ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder( const char* test_case_name, - const char* file, - int line) { + CodeLocation code_location) { ParameterizedTestCaseInfo<TestCase>* typed_test_info = NULL; for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); it != test_case_infos_.end(); ++it) { @@ -578,7 +689,7 @@ class ParameterizedTestCaseRegistry { // 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); + ReportInvalidTestCaseType(test_case_name, code_location); posix::Abort(); } else { // At this point we are sure that the object we found is of the same @@ -591,7 +702,8 @@ class ParameterizedTestCaseRegistry { } } if (typed_test_info == NULL) { - typed_test_info = new ParameterizedTestCaseInfo<TestCase>(test_case_name); + typed_test_info = new ParameterizedTestCaseInfo<TestCase>( + test_case_name, code_location); test_case_infos_.push_back(typed_test_info); } return typed_test_info; |